steep 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE +21 -0
  4. data/bin/smoke_runner.rb +3 -0
  5. data/lib/steep/ast/annotation/collection.rb +120 -43
  6. data/lib/steep/ast/annotation.rb +5 -10
  7. data/lib/steep/ast/location.rb +1 -1
  8. data/lib/steep/ast/method_type.rb +3 -1
  9. data/lib/steep/ast/signature/alias.rb +19 -0
  10. data/lib/steep/ast/signature/env.rb +9 -0
  11. data/lib/steep/ast/signature/members.rb +4 -0
  12. data/lib/steep/ast/types/proc.rb +79 -0
  13. data/lib/steep/ast/types/void.rb +4 -0
  14. data/lib/steep/cli.rb +2 -1
  15. data/lib/steep/drivers/check.rb +4 -1
  16. data/lib/steep/errors.rb +13 -0
  17. data/lib/steep/interface/builder.rb +90 -47
  18. data/lib/steep/interface/instantiated.rb +1 -1
  19. data/lib/steep/interface/method.rb +8 -0
  20. data/lib/steep/interface/method_type.rb +40 -13
  21. data/lib/steep/parser.rb +1098 -1043
  22. data/lib/steep/parser.y +94 -36
  23. data/lib/steep/source.rb +5 -6
  24. data/lib/steep/subtyping/check.rb +162 -47
  25. data/lib/steep/subtyping/variable_occurrence.rb +2 -2
  26. data/lib/steep/subtyping/variable_variance.rb +3 -3
  27. data/lib/steep/type_construction.rb +630 -300
  28. data/lib/steep/type_inference/block_params.rb +186 -35
  29. data/lib/steep/type_inference/send_args.rb +12 -3
  30. data/lib/steep/type_inference/type_env.rb +10 -4
  31. data/lib/steep/type_name.rb +6 -0
  32. data/lib/steep/typing.rb +21 -2
  33. data/lib/steep/version.rb +1 -1
  34. data/lib/steep.rb +2 -0
  35. data/smoke/alias/a.rb +19 -0
  36. data/smoke/alias/a.rbi +10 -0
  37. data/smoke/alias/b.rb +7 -0
  38. data/smoke/alias/c.rb +10 -0
  39. data/smoke/array/c.rb +7 -0
  40. data/smoke/block/c.rb +10 -0
  41. data/smoke/block/c.rbi +3 -0
  42. data/smoke/block/d.rb +15 -0
  43. data/smoke/class/c.rb +1 -1
  44. data/smoke/class/e.rb +1 -1
  45. data/smoke/class/h.rb +15 -0
  46. data/smoke/class/h.rbi +7 -0
  47. data/smoke/class/i.rb +17 -0
  48. data/smoke/class/i.rbi +9 -0
  49. data/smoke/extension/a.rbi +4 -0
  50. data/smoke/extension/d.rb +2 -0
  51. data/smoke/hash/a.rb +17 -0
  52. data/smoke/hash/b.rb +7 -0
  53. data/smoke/implements/a.rb +2 -2
  54. data/smoke/initialize/a.rb +1 -1
  55. data/smoke/lambda/a.rb +11 -0
  56. data/smoke/literal/b.rb +9 -0
  57. data/smoke/literal/literal_methods.rbi +4 -0
  58. data/smoke/method/c.rb +5 -0
  59. data/smoke/regression/array.rb +7 -0
  60. data/smoke/regression/hash.rb +7 -0
  61. data/smoke/regression/set_divide.rb +16 -0
  62. data/smoke/self/a.rb +2 -2
  63. data/stdlib/builtin.rbi +151 -1
  64. data/steep.gemspec +1 -0
  65. metadata +30 -4
@@ -34,6 +34,23 @@ module Steep
34
34
  def boolean?(type)
35
35
  type.is_a?(AST::Types::Boolean)
36
36
  end
37
+
38
+ def optional(type)
39
+ AST::Types::Union.build(types: [type, nil_instance])
40
+ end
41
+
42
+ def hash_instance?(type)
43
+ case type
44
+ when AST::Types::Name
45
+ type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Hash", absolute: true)
46
+ else
47
+ false
48
+ end
49
+ end
50
+
51
+ def array_instance?(type)
52
+ type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Array", absolute: true)
53
+ end
37
54
  end
38
55
 
39
56
  class MethodContext
@@ -122,8 +139,23 @@ module Steep
122
139
  @type_env = type_env
123
140
  end
124
141
 
142
+ def with_new_typing(typing)
143
+ self.class.new(
144
+ checker: checker,
145
+ source: source,
146
+ annotations: annotations,
147
+ type_env: type_env,
148
+ typing: typing,
149
+ self_type: self_type,
150
+ method_context: method_context,
151
+ block_context: block_context,
152
+ module_context: module_context,
153
+ break_context: break_context
154
+ )
155
+ end
156
+
125
157
  def for_new_method(method_name, node, args:, self_type:)
126
- annots = source.annotations(block: node)
158
+ annots = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
127
159
  type_env = TypeInference::TypeEnv.new(subtyping: checker,
128
160
  const_env: module_context&.const_env || self.type_env.const_env)
129
161
 
@@ -131,26 +163,61 @@ module Steep
131
163
  type_env.set(const: name, type: type)
132
164
  end
133
165
 
134
- self_type = annots.self_type || self_type
166
+ self_type = expand_alias(annots.self_type || self_type)
135
167
 
136
168
  self_interface = self_type && (self_type != Types.any || nil) && checker.resolve(self_type, with_initialize: true)
137
- interface_method = self_interface&.yield_self {|interface| interface.methods[method_name] }
138
- annotation_method = annotations.lookup_method_type(method_name)&.yield_self do |method_type|
169
+ interface_method = self_interface&.yield_self do |interface|
170
+ interface.methods[method_name]&.yield_self do |method|
171
+ if self_type.is_a?(AST::Types::Name) && method.type_name == self_type.name
172
+ method
173
+ else
174
+ Interface::Method.new(type_name: self_type,
175
+ name: method_name,
176
+ types: method.types,
177
+ super_method: method,
178
+ attributes: [])
179
+ end
180
+ end
181
+ end
182
+
183
+ annotation_method = annotations.method_type(method_name)&.yield_self do |method_type|
184
+ subst = Interface::Substitution.build([],
185
+ instance_type: module_context&.instance_type || AST::Types::Instance.new,
186
+ module_type: module_context&.module_type || AST::Types::Class.new,
187
+ self_type: self_type)
139
188
  Interface::Method.new(type_name: nil,
140
189
  name: method_name,
141
- types: [checker.builder.method_type_to_method_type(method_type,
142
- current: current_namespace)],
190
+ types: [method_type.subst(subst)],
143
191
  super_method: interface_method&.super_method,
144
192
  attributes: [])
145
193
  end
146
194
 
147
195
  if interface_method && annotation_method
196
+ interface_types = interface_method.types.map do |method_type|
197
+ subst = Interface::Substitution.build(method_type.type_params)
198
+ method_type.instantiate(subst)
199
+ end
200
+
201
+ unknowns = []
202
+ annotation_types = annotation_method.types.each.with_object([]) do |method_type, array|
203
+ fresh = method_type.type_params.map {|var| AST::Types::Var.fresh(var) }
204
+ unknowns.push(*fresh)
205
+
206
+ subst = Interface::Substitution.build(method_type.type_params, fresh)
207
+ array << method_type.instantiate(subst)
208
+ end
209
+
210
+ constraints = Subtyping::Constraints.new(unknowns: unknowns)
211
+ interface_types.each do |type|
212
+ constraints.add_var *type.free_variables.to_a
213
+ end
214
+
148
215
  result = checker.check_method(method_name,
149
- annotation_method,
150
- interface_method,
216
+ annotation_method.with_types(annotation_types),
217
+ interface_method.with_types(interface_types),
151
218
  assumption: Set.new,
152
219
  trace: Subtyping::Trace.new,
153
- constraints: Subtyping::Constraints.empty)
220
+ constraints: constraints)
154
221
 
155
222
  if result.failure?
156
223
  typing.add_error Errors::IncompatibleMethodTypeAnnotation.new(
@@ -168,10 +235,22 @@ module Steep
168
235
  when method && method.types.size == 1
169
236
  method_type = method.types.first
170
237
  return_type = method_type.return_type
171
- var_types = TypeConstruction.parameter_types(args, method_type).transform_values {|type| absolute_type(type) }
238
+ var_types = TypeConstruction.parameter_types(args, method_type)
172
239
  unless TypeConstruction.valid_parameter_env?(var_types, args.reject {|arg| arg.type == :blockarg }, method_type.params)
173
240
  typing.add_error Errors::MethodArityMismatch.new(node: node)
174
241
  end
242
+
243
+ if (block_arg = args.find {|arg| arg.type == :blockarg })
244
+ if method_type.block
245
+ block_type = if method_type.block.optional?
246
+ AST::Types::Union.build(types: [method_type.block.type, Types.nil_instance])
247
+ else
248
+ method_type.block.type
249
+ end
250
+ var_types[block_arg.children[0].name] = block_type
251
+ end
252
+ end
253
+
175
254
  when method
176
255
  typing.add_error Errors::MethodDefinitionWithOverloading.new(node: node, method: method)
177
256
  return_type = union_type(*method.types.map(&:return_type))
@@ -214,9 +293,9 @@ module Steep
214
293
  end
215
294
 
216
295
  type_env = type_env.with_annotations(
217
- lvar_types: annots.var_types.transform_values {|annot| absolute_type(annot.type) },
296
+ lvar_types: annots.lvar_types,
218
297
  ivar_types: annots.ivar_types,
219
- const_types: annots.const_types.transform_values {|type| absolute_type(type) }
298
+ const_types: annots.const_types,
220
299
  )
221
300
 
222
301
  self.class.new(
@@ -234,23 +313,33 @@ module Steep
234
313
  end
235
314
 
236
315
  def for_module(node)
237
- annots = source.annotations(block: node)
238
316
  new_module_name = ModuleName.from_node(node.children.first) or raise "Unexpected module name: #{node.children.first}"
317
+ new_namespace = nested_namespace(new_module_name)
239
318
 
319
+ annots = source.annotations(block: node, builder: checker.builder, current_module: new_namespace)
240
320
  module_type = AST::Types::Name.new_instance(name: "::Module")
241
321
 
242
- implement_module_name =
243
- if annots.implement_module
244
- annots.implement_module.name
322
+ implement_module_name = yield_self do
323
+ if (annotation = annots.implement_module_annotation)
324
+ absolute_name(annotation.name.name).yield_self do |absolute_name|
325
+ if checker.builder.signatures.module_name?(absolute_name)
326
+ AST::Annotation::Implements::Module.new(name: absolute_name,
327
+ args: annotation.name.args)
328
+ else
329
+ Steep.logger.error "Unknown module name given to @implements: #{annotation.name.name}"
330
+ nil
331
+ end
332
+ end
245
333
  else
246
- absolute_name(new_module_name).yield_self do |module_name|
247
- if checker.builder.signatures.module_name?(module_name)
248
- signature = checker.builder.signatures.find_module(module_name)
249
- AST::Annotation::Implements::Module.new(name: module_name,
334
+ absolute_name(new_module_name).yield_self do |absolute_name|
335
+ if checker.builder.signatures.module_name?(absolute_name)
336
+ signature = checker.builder.signatures.find_module(absolute_name)
337
+ AST::Annotation::Implements::Module.new(name: absolute_name,
250
338
  args: signature.params&.variables || [])
251
339
  end
252
340
  end
253
341
  end
342
+ end
254
343
 
255
344
  if implement_module_name
256
345
  module_name = implement_module_name.name
@@ -258,9 +347,7 @@ module Steep
258
347
 
259
348
  abstract = checker.builder.build(TypeName::Instance.new(name: module_name))
260
349
 
261
- instance_type = absolute_type(
262
- AST::Types::Name.new_instance(name: module_name, args: module_args)
263
- )
350
+ instance_type = AST::Types::Name.new_instance(name: module_name, args: module_args)
264
351
 
265
352
  unless abstract.supers.empty?
266
353
  instance_type = AST::Types::Intersection.build(
@@ -275,19 +362,18 @@ module Steep
275
362
  end
276
363
 
277
364
  if annots.instance_type
278
- instance_type = absolute_type(annots.instance_type)
365
+ instance_type = annots.instance_type
279
366
  end
280
367
 
281
368
  if annots.module_type
282
- module_type = absolute_type(annots.module_type)
369
+ module_type = annots.module_type
283
370
  end
284
371
 
285
- new_namespace = nested_namespace(new_module_name)
286
372
  module_const_env = TypeInference::ConstantEnv.new(builder: checker.builder, current_namespace: new_namespace)
287
373
 
288
374
  module_context_ = ModuleContext.new(
289
375
  instance_type: instance_type,
290
- module_type: module_type,
376
+ module_type: annots.self_type || module_type,
291
377
  implement_name: implement_module_name,
292
378
  current_namespace: new_namespace,
293
379
  const_env: module_const_env
@@ -313,21 +399,32 @@ module Steep
313
399
  end
314
400
 
315
401
  def for_class(node)
316
- annots = source.annotations(block: node)
317
402
  new_class_name = ModuleName.from_node(node.children.first) or raise "Unexpected class name: #{node.children.first}"
403
+ new_namespace = nested_namespace(new_class_name)
318
404
 
319
- implement_module_name =
320
- if annots.implement_module
321
- annots.implement_module.name
405
+ annots = source.annotations(block: node, builder: checker.builder, current_module: new_namespace)
406
+
407
+ implement_module_name = yield_self do
408
+ if (annotation = annots.implement_module_annotation)
409
+ absolute_name(annotation.name.name).yield_self do |absolute_name|
410
+ if checker.builder.signatures.class_name?(absolute_name)
411
+ AST::Annotation::Implements::Module.new(name: absolute_name,
412
+ args: annotation.name.args)
413
+ else
414
+ Steep.logger.error "Unknown class name given to @implements: #{annotation.name.name}"
415
+ nil
416
+ end
417
+ end
322
418
  else
323
- absolute_name(new_class_name).yield_self do |name|
324
- if checker.builder.signatures.class_name?(name)
325
- signature = checker.builder.signatures.find_class(name)
326
- AST::Annotation::Implements::Module.new(name: name,
419
+ absolute_name(new_class_name).yield_self do |absolute_name|
420
+ if checker.builder.signatures.class_name?(absolute_name)
421
+ signature = checker.builder.signatures.find_class(absolute_name)
422
+ AST::Annotation::Implements::Module.new(name: absolute_name,
327
423
  args: signature.params&.variables || [])
328
424
  end
329
425
  end
330
426
  end
427
+ end
331
428
 
332
429
  if implement_module_name
333
430
  class_name = implement_module_name.name
@@ -336,15 +433,14 @@ module Steep
336
433
  _ = checker.builder.build(TypeName::Instance.new(name: class_name))
337
434
 
338
435
  instance_type = AST::Types::Name.new_instance(name: class_name, args: class_args)
339
- module_type = AST::Types::Name.new_class(name: class_name, args: [], constructor: nil)
436
+ module_type = AST::Types::Name.new_class(name: class_name, args: [], constructor: true)
340
437
  end
341
438
 
342
- new_namespace = nested_namespace(new_class_name)
343
439
  class_const_env = TypeInference::ConstantEnv.new(builder: checker.builder, current_namespace: new_namespace)
344
440
 
345
441
  module_context = ModuleContext.new(
346
442
  instance_type: annots.instance_type || instance_type,
347
- module_type: annots.module_type || module_type,
443
+ module_type: annots.self_type || annots.module_type || module_type,
348
444
  implement_name: implement_module_name,
349
445
  current_namespace: new_namespace,
350
446
  const_env: class_const_env
@@ -372,13 +468,13 @@ module Steep
372
468
  end
373
469
 
374
470
  def for_branch(node, truthy_vars: Set.new, type_case_override: nil)
375
- annots = source.annotations(block: node)
471
+ annots = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
376
472
 
377
473
  type_env = self.type_env
378
474
 
379
475
  lvar_types = self.type_env.lvar_types.each.with_object({}) do |(var, type), env|
380
476
  if truthy_vars.member?(var)
381
- env[var] = TypeConstruction.unwrap(type)
477
+ env[var] = unwrap(type)
382
478
  else
383
479
  env[var] = type
384
480
  end
@@ -399,9 +495,9 @@ module Steep
399
495
  end
400
496
 
401
497
  type_env = type_env.with_annotations(
402
- lvar_types: annots.var_types.transform_values {|a| absolute_type(a.type) },
403
- ivar_types: annots.ivar_types.transform_values {|ty| absolute_type(ty) },
404
- const_types: annots.const_types.transform_values {|ty| absolute_type(ty) },
498
+ lvar_types: annots.lvar_types,
499
+ ivar_types: annots.ivar_types,
500
+ const_types: annots.const_types,
405
501
  gvar_types: {}
406
502
  ) do |var, relation, result|
407
503
  typing.add_error(
@@ -438,9 +534,15 @@ module Steep
438
534
  case node.type
439
535
  when :begin, :kwbegin
440
536
  yield_self do
441
- type = each_child_node(node).map do |child|
442
- synthesize(child, hint: hint)
443
- end.last
537
+ *mid_nodes, last_node = each_child_node(node).to_a
538
+ mid_nodes.each do |child|
539
+ synthesize(child)
540
+ end
541
+ if last_node
542
+ type = synthesize(last_node, hint: hint)
543
+ else
544
+ type = Types.nil_instance
545
+ end
444
546
 
445
547
  typing.add_typing(node, type)
446
548
  end
@@ -451,9 +553,10 @@ module Steep
451
553
  rhs = node.children[1]
452
554
 
453
555
  if var.name == :_
556
+ synthesize(rhs, hint: Types.any)
454
557
  typing.add_typing(node, Types.any)
455
558
  else
456
- type_assignment(var, rhs, node)
559
+ type_assignment(var, rhs, node, hint: hint)
457
560
  end
458
561
  end
459
562
 
@@ -485,7 +588,7 @@ module Steep
485
588
  when :send
486
589
  yield_self do
487
590
  if self_class?(node)
488
- module_type = module_context.module_type
591
+ module_type = expand_alias(module_context.module_type)
489
592
  type = if module_type.is_a?(AST::Types::Name) && module_type.name.is_a?(TypeName::Class)
490
593
  AST::Types::Name.new(name: module_type.name.updated(constructor: method_context.constructor),
491
594
  args: module_type.args)
@@ -501,7 +604,7 @@ module Steep
501
604
  when :csend
502
605
  yield_self do
503
606
  type = if self_class?(node)
504
- module_type = module_context.module_type
607
+ module_type = expand_alias(module_context.module_type)
505
608
  type = if module_type.is_a?(AST::Types::Name)
506
609
  AST::Types::Name.new(name: module_type.name.updated(constructor: method_context.constructor),
507
610
  args: module_type.args)
@@ -622,7 +725,11 @@ module Steep
622
725
  when :block
623
726
  yield_self do
624
727
  send_node, params, body = node.children
625
- type_send(node, send_node: send_node, block_params: params, block_body: body)
728
+ if send_node.type == :lambda
729
+ type_lambda(node, block_params: params, block_body: body, type_hint: hint)
730
+ else
731
+ type_send(node, send_node: send_node, block_params: params, block_body: body)
732
+ end
626
733
  end
627
734
 
628
735
  when :def
@@ -636,11 +743,11 @@ module Steep
636
743
  end
637
744
 
638
745
  if node.children[2]
639
- return_type = new.method_context&.return_type
746
+ return_type = expand_alias(new.method_context&.return_type)
640
747
  if return_type && !return_type.is_a?(AST::Types::Void)
641
748
  new.check(node.children[2], return_type) do |_, actual_type, result|
642
749
  typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
643
- expected: return_type,
750
+ expected: new.method_context&.return_type,
644
751
  actual: actual_type,
645
752
  result: result))
646
753
  end
@@ -648,7 +755,7 @@ module Steep
648
755
  new.synthesize(node.children[2])
649
756
  end
650
757
  else
651
- return_type = new.method_context&.return_type
758
+ return_type = expand_alias(new.method_context&.return_type)
652
759
  if return_type && !return_type.is_a?(AST::Types::Void)
653
760
  result = checker.check(
654
761
  Subtyping::Relation.new(sub_type: Types.nil_instance, super_type: return_type),
@@ -656,7 +763,7 @@ module Steep
656
763
  )
657
764
  if result.failure?
658
765
  typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
659
- expected: return_type,
766
+ expected: new.method_context&.return_type,
660
767
  actual: Types.nil_instance,
661
768
  result: result))
662
769
  end
@@ -681,7 +788,7 @@ module Steep
681
788
  end
682
789
 
683
790
  if node.children[3]
684
- return_type = new.method_context&.return_type
791
+ return_type = expand_alias(new.method_context&.return_type)
685
792
  if return_type && !return_type.is_a?(AST::Types::Void)
686
793
  new.check(node.children[3], return_type) do |return_type, actual_type, result|
687
794
  typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
@@ -716,18 +823,20 @@ module Steep
716
823
  Types.array_instance(union_type(*return_types))
717
824
  end
718
825
 
719
- if method_context&.return_type && !method_context.return_type.is_a?(AST::Types::Void)
720
- result = checker.check(
721
- Subtyping::Relation.new(sub_type: value_type,
722
- super_type: method_context.return_type),
723
- constraints: Subtyping::Constraints.empty
724
- )
725
-
726
- if result.failure?
727
- typing.add_error(Errors::ReturnTypeMismatch.new(node: node,
728
- expected: method_context.return_type,
729
- actual: value_type,
730
- result: result))
826
+ if (ret_type = expand_alias(method_context&.return_type))
827
+ unless ret_type.is_a?(AST::Types::Void)
828
+ result = checker.check(
829
+ Subtyping::Relation.new(sub_type: value_type,
830
+ super_type: ret_type),
831
+ constraints: Subtyping::Constraints.empty
832
+ )
833
+
834
+ if result.failure?
835
+ typing.add_error(Errors::ReturnTypeMismatch.new(node: node,
836
+ expected: method_context&.return_type,
837
+ actual: value_type,
838
+ result: result))
839
+ end
731
840
  end
732
841
  end
733
842
  end
@@ -804,7 +913,7 @@ module Steep
804
913
  yield_self do
805
914
  var = node.children[0]
806
915
  rhs = node.children[1]
807
- type_assignment(var, rhs, node)
916
+ type_assignment(var, rhs, node, hint: hint)
808
917
  end
809
918
 
810
919
  when :restarg
@@ -837,7 +946,7 @@ module Steep
837
946
 
838
947
  when :int
839
948
  yield_self do
840
- literal_type = test_literal_type(node.children[0], hint)
949
+ literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
841
950
 
842
951
  if literal_type
843
952
  typing.add_typing(node, literal_type)
@@ -848,7 +957,7 @@ module Steep
848
957
 
849
958
  when :sym
850
959
  yield_self do
851
- literal_type = test_literal_type(node.children[0], hint)
960
+ literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
852
961
 
853
962
  if literal_type
854
963
  typing.add_typing(node, literal_type)
@@ -859,7 +968,7 @@ module Steep
859
968
 
860
969
  when :str
861
970
  yield_self do
862
- literal_type = test_literal_type(node.children[0], hint)
971
+ literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
863
972
 
864
973
  if literal_type
865
974
  typing.add_typing(node, literal_type)
@@ -873,6 +982,11 @@ module Steep
873
982
 
874
983
  when :hash
875
984
  yield_self do
985
+ if Types.hash_instance?(hint)
986
+ key_hint = hint.args[0]
987
+ value_hint = hint.args[1]
988
+ end
989
+
876
990
  key_types = []
877
991
  value_types = []
878
992
 
@@ -880,18 +994,22 @@ module Steep
880
994
  case child.type
881
995
  when :pair
882
996
  key, value = child.children
883
- key_types << synthesize(key)
884
- value_types << synthesize(value)
997
+ key_types << synthesize(key).yield_self do |type|
998
+ select_super_type(type, key_hint)
999
+ end
1000
+ value_types << synthesize(value).yield_self do |type|
1001
+ select_super_type(type, value_hint)
1002
+ end
885
1003
  when :kwsplat
886
- splat_type = synthesize(child.children[0])
887
-
888
- if splat_type.is_a?(AST::Types::Name) && splat_type.name == TypeName::Instance.new(name: ModuleName.parse("::Hash"))
889
- key_types << splat_type.args[0]
890
- value_types << splat_type.args[1]
891
- else
892
- typing.add_error Errors::UnexpectedSplat.new(node: child, type: splat_type)
893
- key_types << Types.any
894
- value_types << Types.any
1004
+ expand_alias(synthesize(child.children[0])) do |splat_type, original_type|
1005
+ if splat_type.is_a?(AST::Types::Name) && splat_type.name == TypeName::Instance.new(name: ModuleName.parse("::Hash"))
1006
+ key_types << splat_type.args[0]
1007
+ value_types << splat_type.args[1]
1008
+ else
1009
+ typing.add_error Errors::UnexpectedSplat.new(node: child, type: original_type)
1010
+ key_types << Types.any
1011
+ value_types << Types.any
1012
+ end
895
1013
  end
896
1014
  else
897
1015
  raise "Unexpected non pair: #{child.inspect}" unless child.type == :pair
@@ -901,10 +1019,14 @@ module Steep
901
1019
  key_type = key_types.empty? ? Types.any : AST::Types::Union.build(types: key_types)
902
1020
  value_type = value_types.empty? ? Types.any : AST::Types::Union.build(types: value_types)
903
1021
 
1022
+ if key_types.empty? && value_types.empty? && !hint
1023
+ typing.add_error Errors::FallbackAny.new(node: node)
1024
+ end
1025
+
904
1026
  typing.add_typing(node, Types.hash_instance(key_type, value_type))
905
1027
  end
906
1028
 
907
- when :dstr
1029
+ when :dstr, :xstr
908
1030
  each_child_node(node) do |child|
909
1031
  synthesize(child)
910
1032
  end
@@ -991,7 +1113,7 @@ module Steep
991
1113
  if method_context&.method_type
992
1114
  if method_context.block_type
993
1115
  block_type = method_context.block_type
994
- block_type.params.flat_unnamed_params.map(&:last).zip(node.children).each do |(type, node)|
1116
+ block_type.type.params.flat_unnamed_params.map(&:last).zip(node.children).each do |(type, node)|
995
1117
  if node && type
996
1118
  check(node, type) do |_, rhs_type, result|
997
1119
  typing.add_error(Errors::IncompatibleAssignment.new(node: node,
@@ -1002,7 +1124,7 @@ module Steep
1002
1124
  end
1003
1125
  end
1004
1126
 
1005
- typing.add_typing(node, block_type.return_type)
1127
+ typing.add_typing(node, block_type.type.return_type)
1006
1128
  else
1007
1129
  typing.add_error(Errors::UnexpectedYield.new(node: node))
1008
1130
  fallback_to_any node
@@ -1015,8 +1137,13 @@ module Steep
1015
1137
  yield_self do
1016
1138
  if method_context&.method
1017
1139
  if method_context.super_method
1018
- types = method_context.super_method.types.map(&:return_type)
1019
- typing.add_typing(node, union_type(*types))
1140
+ if method_context.method.incompatible?
1141
+ typing.add_error Errors::IncompatibleZuper.new(node: node, method: method_context.name)
1142
+ typing.add_typing node, Types.any
1143
+ else
1144
+ types = method_context.super_method.types.map(&:return_type)
1145
+ typing.add_typing(node, union_type(*types))
1146
+ end
1020
1147
  else
1021
1148
  typing.add_error(Errors::UnexpectedSuper.new(node: node, method: method_context.name))
1022
1149
  fallback_to_any node
@@ -1029,35 +1156,48 @@ module Steep
1029
1156
  when :array
1030
1157
  yield_self do
1031
1158
  if node.children.empty?
1159
+ unless hint
1160
+ typing.add_error Errors::FallbackAny.new(node: node)
1161
+ end
1032
1162
  typing.add_typing(node, Types.array_instance(Types.any))
1033
1163
  else
1034
- is_tuple = hint.is_a?(AST::Types::Tuple)
1035
- is_tuple &&= node.children.all? {|child| child.type != :splat }
1036
- is_tuple &&= node.children.map.with_index do |child, index|
1037
- synthesize(child, hint: absolute_type(hint.types[index]))
1038
- end.yield_self do |types|
1039
- tuple = AST::Types::Tuple.new(types: types)
1040
- relation = Subtyping::Relation.new(sub_type: tuple, super_type: absolute_type(hint))
1041
- result = checker.check(relation, constraints: Subtyping::Constraints.empty)
1042
- result.success?
1164
+ is_tuple = nil
1165
+
1166
+ expand_alias(hint) do |hint|
1167
+ is_tuple = hint.is_a?(AST::Types::Tuple)
1168
+ is_tuple &&= node.children.all? {|child| child.type != :splat }
1169
+ is_tuple &&= node.children.map.with_index do |child, index|
1170
+ synthesize(child, hint: hint.types[index])
1171
+ end.yield_self do |types|
1172
+ tuple = AST::Types::Tuple.new(types: types)
1173
+ relation = Subtyping::Relation.new(sub_type: tuple, super_type: hint)
1174
+ result = checker.check(relation, constraints: Subtyping::Constraints.empty)
1175
+ result.success?
1176
+ end
1043
1177
  end
1044
1178
 
1045
1179
  if is_tuple
1046
1180
  array_type = hint
1047
1181
  else
1182
+ element_hint = expand_alias(hint) do |hint|
1183
+ Types.array_instance?(hint) && hint.args[0]
1184
+ end
1185
+
1048
1186
  element_types = node.children.flat_map do |e|
1049
1187
  if e.type == :splat
1050
1188
  Steep.logger.info "Typing of splat in array is incompatible with Ruby; it does not use #to_a method"
1051
1189
  synthesize(e.children.first).yield_self do |type|
1052
- case type
1053
- when AST::Types::Union
1054
- type.types
1055
- else
1056
- [type]
1190
+ expand_alias(type) do |ty|
1191
+ case ty
1192
+ when AST::Types::Union
1193
+ ty.types
1194
+ else
1195
+ [ty]
1196
+ end
1057
1197
  end
1058
1198
  end.map do |type|
1059
1199
  case
1060
- when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Array", absolute: true)
1200
+ when Types.array_instance?(type)
1061
1201
  type.args.first
1062
1202
  when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Range", absolute: true)
1063
1203
  type.args.first
@@ -1066,7 +1206,7 @@ module Steep
1066
1206
  end
1067
1207
  end
1068
1208
  else
1069
- [synthesize(e)]
1209
+ [select_super_type(synthesize(e), element_hint)]
1070
1210
  end
1071
1211
  end
1072
1212
  array_type = Types.array_instance(AST::Types::Union.build(types: element_types))
@@ -1098,9 +1238,11 @@ module Steep
1098
1238
  end
1099
1239
 
1100
1240
  when :or
1101
- types = each_child_node(node).map {|child| synthesize(child) }
1102
- type = union_type(*types)
1103
- typing.add_typing(node, type)
1241
+ yield_self do
1242
+ t1, t2 = each_child_node(node).map {|child| synthesize(child) }
1243
+ type = union_type(unwrap(t1), t2)
1244
+ typing.add_typing(node, type)
1245
+ end
1104
1246
 
1105
1247
  when :if
1106
1248
  cond, true_clause, false_clause = node.children
@@ -1129,7 +1271,7 @@ module Steep
1129
1271
  cond, *whens = node.children
1130
1272
 
1131
1273
  if cond
1132
- cond_type = synthesize(cond)
1274
+ cond_type = expand_alias(synthesize(cond))
1133
1275
  if cond_type.is_a?(AST::Types::Union)
1134
1276
  var_names = TypeConstruction.value_variables(cond)
1135
1277
  var_types = cond_type.types.dup
@@ -1139,7 +1281,7 @@ module Steep
1139
1281
  pairs = whens.each.with_object([]) do |clause, pairs|
1140
1282
  if clause&.type == :when
1141
1283
  test_types = clause.children.take(clause.children.size - 1).map do |child|
1142
- synthesize(child, hint: hint)
1284
+ expand_alias(synthesize(child, hint: hint))
1143
1285
  end
1144
1286
 
1145
1287
  if (body = clause.children.last)
@@ -1240,6 +1382,7 @@ module Steep
1240
1382
  case
1241
1383
  when exn_classes && var_name
1242
1384
  instance_types = exn_types.map do |type|
1385
+ type = expand_alias(type)
1243
1386
  case
1244
1387
  when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Class)
1245
1388
  type.instance_type
@@ -1374,7 +1517,47 @@ module Steep
1374
1517
  end
1375
1518
  end
1376
1519
 
1377
- when :splat, :block_pass, :blockarg, :sclass
1520
+ when :block_pass
1521
+ yield_self do
1522
+ value = node.children[0]
1523
+
1524
+ if hint.is_a?(AST::Types::Proc) && value.type == :sym
1525
+ if hint.one_arg?
1526
+ # Assumes Symbol#to_proc implementation
1527
+ param_type = hint.params.required[0]
1528
+ interface = checker.resolve(param_type, with_initialize: false)
1529
+ method = interface.methods[value.children[0]]
1530
+ if method
1531
+ return_types = method.types.flat_map do |method_type|
1532
+ if method_type.params.each_type.count == 0
1533
+ [method_type.return_type]
1534
+ end
1535
+ end
1536
+
1537
+ if return_types.any?
1538
+ type = AST::Types::Proc.new(params: Interface::Params.empty.update(required: [param_type]),
1539
+ return_type: AST::Types::Union.build(types: return_types))
1540
+ end
1541
+ end
1542
+ else
1543
+ Steep.logger.error "Passing multiple args through Symbol#to_proc is not supported yet"
1544
+ end
1545
+ end
1546
+
1547
+ type ||= synthesize(node.children[0], hint: hint)
1548
+ typing.add_typing node, type
1549
+ end
1550
+
1551
+ when :blockarg
1552
+ yield_self do
1553
+ each_child_node node do |child|
1554
+ synthesize(child)
1555
+ end
1556
+
1557
+ typing.add_typing node, Types.any
1558
+ end
1559
+
1560
+ when :splat, :sclass
1378
1561
  yield_self do
1379
1562
  Steep.logger.error "Unsupported node #{node.type}"
1380
1563
 
@@ -1404,11 +1587,12 @@ module Steep
1404
1587
  end
1405
1588
  end
1406
1589
 
1407
- def type_assignment(var, rhs, node)
1590
+ def type_assignment(var, rhs, node, hint: nil)
1408
1591
  if rhs
1409
- rhs_type = synthesize(rhs, hint: type_env.lvar_types[var.name])
1410
- node_type = assign_type_to_variable(var, rhs_type, node)
1411
- typing.add_typing(node, node_type)
1592
+ expand_alias(synthesize(rhs, hint: type_env.lvar_types[var.name] || hint)) do |rhs_type|
1593
+ node_type = assign_type_to_variable(var, rhs_type, node)
1594
+ typing.add_typing(node, node_type)
1595
+ end
1412
1596
  else
1413
1597
  raise
1414
1598
  lhs_type = variable_type(var)
@@ -1433,7 +1617,7 @@ module Steep
1433
1617
  end
1434
1618
 
1435
1619
  def type_ivasgn(name, rhs, node)
1436
- rhs_type = synthesize(rhs)
1620
+ rhs_type = synthesize(rhs, hint: type_env.get(ivar: name) { fallback_to_any(node) })
1437
1621
  ivar_type = type_env.assign(ivar: name, type: rhs_type) do |error|
1438
1622
  case error
1439
1623
  when Subtyping::Result::Failure
@@ -1451,7 +1635,8 @@ module Steep
1451
1635
 
1452
1636
  def type_masgn(node)
1453
1637
  lhs, rhs = node.children
1454
- rhs_type = synthesize(rhs)
1638
+ rhs_original = synthesize(rhs)
1639
+ rhs_type = expand_alias(rhs_original)
1455
1640
 
1456
1641
  case
1457
1642
  when rhs.type == :array && lhs.children.all? {|a| a.type == :lvasgn || a.type == :ivasgn } && lhs.children.size == rhs.children.size
@@ -1564,12 +1749,32 @@ module Steep
1564
1749
  end
1565
1750
  end
1566
1751
 
1752
+ def type_lambda(node, block_params:, block_body:, type_hint:)
1753
+ block_annotations = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
1754
+ params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
1755
+
1756
+ case type_hint
1757
+ when AST::Types::Proc
1758
+ params_hint = type_hint.params
1759
+ return_hint = type_hint.return_type
1760
+ end
1761
+
1762
+ block_type = type_block(block_param_hint: params_hint,
1763
+ block_type_hint: return_hint,
1764
+ node_type_hint: nil,
1765
+ block_params: params,
1766
+ block_body: block_body,
1767
+ block_annotations: block_annotations)
1768
+
1769
+ typing.add_typing node, block_type
1770
+ end
1771
+
1567
1772
  def type_send(node, send_node:, block_params:, block_body:, unwrap: false)
1568
1773
  receiver, method_name, *arguments = send_node.children
1569
1774
  receiver_type = receiver ? synthesize(receiver) : self_type
1570
1775
 
1571
1776
  if unwrap
1572
- receiver_type = TypeConstruction.unwrap(receiver_type)
1777
+ receiver_type = unwrap(receiver_type)
1573
1778
  end
1574
1779
 
1575
1780
  case receiver_type
@@ -1624,7 +1829,7 @@ module Steep
1624
1829
 
1625
1830
  if block_body && block_params
1626
1831
  unless typing.has_type?(block_body)
1627
- block_annotations = source.annotations(block: node)
1832
+ block_annotations = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
1628
1833
  params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
1629
1834
  pairs = params.each.map {|param| [param, Types.any] }
1630
1835
 
@@ -1643,45 +1848,45 @@ module Steep
1643
1848
  block_type_env = type_env.dup.yield_self do |env|
1644
1849
  param_pairs.each do |param, type|
1645
1850
  if param.type
1646
- env.set(lvar: param.var.name, type: absolute_type(param.type))
1851
+ env.set(lvar: param.var.name, type: param.type)
1647
1852
  else
1648
- env.set(lvar: param.var.name, type: absolute_type(type))
1853
+ env.set(lvar: param.var.name, type: type)
1649
1854
  end
1650
1855
  end
1651
1856
 
1652
1857
  env.with_annotations(
1653
- lvar_types: block_annotations.var_types.transform_values {|annot| absolute_type(annot.type) },
1654
- ivar_types: block_annotations.ivar_types.transform_values {|type| absolute_type(type) },
1655
- const_types: block_annotations.const_types.transform_values {|type| absolute_type(type) }
1858
+ lvar_types: block_annotations.lvar_types,
1859
+ ivar_types: block_annotations.ivar_types,
1860
+ const_types: block_annotations.const_types,
1656
1861
  )
1657
1862
  end
1658
1863
 
1659
1864
  return_type = if block_annotations.break_type
1660
- union_type(method_return_type, absolute_type(block_annotations.break_type))
1865
+ union_type(method_return_type, block_annotations.break_type)
1661
1866
  else
1662
1867
  method_return_type
1663
1868
  end
1664
1869
  Steep.logger.debug("return_type = #{return_type}")
1665
1870
 
1666
- block_context = BlockContext.new(body_type: absolute_type(block_annotations.block_type))
1871
+ block_context = BlockContext.new(body_type: block_annotations.block_type)
1667
1872
  Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
1668
1873
 
1669
1874
  break_context = BreakContext.new(
1670
- break_type: absolute_type(block_annotations.break_type) || method_return_type,
1671
- next_type: absolute_type(block_annotations.block_type)
1875
+ break_type: block_annotations.break_type || method_return_type,
1876
+ next_type: block_annotations.block_type
1672
1877
  )
1673
- Steep.logger.debug("break_context { type: #{absolute_type(break_context.break_type)} }")
1878
+ Steep.logger.debug("break_context { type: #{break_context.break_type} }")
1674
1879
 
1675
1880
  [self.class.new(
1676
1881
  checker: checker,
1677
1882
  source: source,
1678
- annotations: annotations + block_annotations,
1883
+ annotations: annotations.merge_block_annotations(block_annotations),
1679
1884
  type_env: block_type_env,
1680
1885
  block_context: block_context,
1681
1886
  typing: typing,
1682
1887
  method_context: method_context,
1683
1888
  module_context: module_context,
1684
- self_type: absolute_type(block_annotations.self_type) || self_type,
1889
+ self_type: block_annotations.self_type || self_type,
1685
1890
  break_context: break_context
1686
1891
  ), return_type]
1687
1892
  end
@@ -1689,203 +1894,291 @@ module Steep
1689
1894
  def type_method_call(node, receiver_type:, method:, args:, block_params:, block_body:)
1690
1895
  results = method.types.map do |method_type|
1691
1896
  Steep.logger.tagged method_type.location&.source do
1692
- arg_pairs = args.zip(method_type.params)
1693
-
1694
- if arg_pairs
1695
- try_method_type(node,
1696
- receiver_type: receiver_type,
1697
- method_type: method_type,
1698
- arg_pairs: arg_pairs,
1699
- block_params: block_params,
1700
- block_body: block_body)
1701
- else
1702
- Steep.logger.debug(node.inspect)
1703
- Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
1704
- end
1897
+ child_typing = typing.new_child
1898
+ arg_pairs = args.zip(method_type.params, method_type.block&.type)
1899
+
1900
+ type_or_error = if arg_pairs
1901
+ self.with_new_typing(child_typing).try_method_type(
1902
+ node,
1903
+ receiver_type: receiver_type,
1904
+ method_type: method_type,
1905
+ args: args,
1906
+ arg_pairs: arg_pairs,
1907
+ block_params: block_params,
1908
+ block_body: block_body,
1909
+ child_typing: child_typing
1910
+ )
1911
+ else
1912
+ Steep.logger.debug(node.inspect)
1913
+ Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
1914
+ end
1915
+
1916
+ [child_typing, type_or_error, method_type]
1705
1917
  end
1706
1918
  end
1707
1919
 
1708
- if results.all? {|result| result.is_a?(Errors::Base) }
1709
- results.first
1920
+ if (success = results.find {|_, type_or_error| !type_or_error.is_a?(Errors::Base) })
1921
+ child_typing, type, _ = success
1922
+ child_typing.save!
1923
+ type
1710
1924
  else
1711
- results.find do |result|
1712
- !result.is_a?(Errors::Base)
1925
+ child_typing, error, method_type = results.first
1926
+ typing.add_error error
1927
+ child_typing.save!
1928
+
1929
+ case method_type.return_type
1930
+ when AST::Types::Var
1931
+ Types.any
1932
+ else
1933
+ method_type.return_type
1713
1934
  end
1714
1935
  end
1715
1936
  end
1716
1937
 
1717
- def try_method_type(node, receiver_type:, method_type:, arg_pairs:, block_params:, block_body:)
1938
+ def try_method_type(node, receiver_type:, method_type:, args:, arg_pairs:, block_params:, block_body:, child_typing:)
1718
1939
  fresh_types = method_type.type_params.map {|x| AST::Types::Var.fresh(x) }
1719
1940
  fresh_vars = Set.new(fresh_types.map(&:name))
1720
1941
  instantiation = Interface::Substitution.build(method_type.type_params, fresh_types)
1721
1942
 
1722
- typing.new_child do |child_typing|
1723
- construction = self.class.new(
1724
- checker: checker,
1725
- source: source,
1726
- annotations: annotations,
1727
- type_env: type_env,
1728
- typing: child_typing,
1729
- self_type: self_type,
1730
- method_context: method_context,
1731
- block_context: block_context,
1732
- module_context: module_context,
1733
- break_context: break_context
1734
- )
1943
+ construction = self.class.new(
1944
+ checker: checker,
1945
+ source: source,
1946
+ annotations: annotations,
1947
+ type_env: type_env,
1948
+ typing: child_typing,
1949
+ self_type: self_type,
1950
+ method_context: method_context,
1951
+ block_context: block_context,
1952
+ module_context: module_context,
1953
+ break_context: break_context
1954
+ )
1735
1955
 
1736
- method_type.instantiate(instantiation).yield_self do |method_type|
1737
- constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
1738
- variance = Subtyping::VariableVariance.from_method_type(method_type)
1739
- occurence = Subtyping::VariableOccurence.from_method_type(method_type)
1956
+ method_type.instantiate(instantiation).yield_self do |method_type|
1957
+ constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
1958
+ variance = Subtyping::VariableVariance.from_method_type(method_type)
1959
+ occurence = Subtyping::VariableOccurence.from_method_type(method_type)
1740
1960
 
1741
- arg_pairs.each do |(arg_node, param_type)|
1742
- arg_type = if arg_node.type == :splat
1743
- type = construction.synthesize(arg_node.children[0])
1744
- child_typing.add_typing(arg_node, Types.array_instance(type))
1745
- else
1746
- construction.synthesize(arg_node, hint: param_type)
1747
- end
1961
+ arg_pairs.each do |(arg_node, param_type)|
1962
+ arg_type = if arg_node.type == :splat
1963
+ type = construction.synthesize(arg_node.children[0])
1964
+ child_typing.add_typing(arg_node, type)
1965
+ else
1966
+ construction.synthesize(arg_node, hint: param_type)
1967
+ end
1748
1968
 
1749
- relation = Subtyping::Relation.new(
1750
- sub_type: arg_type,
1751
- super_type: param_type.subst(instantiation)
1752
- )
1969
+ relation = Subtyping::Relation.new(
1970
+ sub_type: arg_type,
1971
+ super_type: param_type.subst(instantiation)
1972
+ )
1753
1973
 
1754
- checker.check(relation, constraints: constraints).else do |result|
1755
- return Errors::ArgumentTypeMismatch.new(
1756
- node: arg_node,
1757
- receiver_type: receiver_type,
1758
- expected: relation.super_type,
1759
- actual: relation.sub_type
1760
- )
1761
- end
1974
+ checker.check(relation, constraints: constraints).else do |result|
1975
+ return Errors::ArgumentTypeMismatch.new(
1976
+ node: arg_node,
1977
+ receiver_type: receiver_type,
1978
+ expected: relation.super_type,
1979
+ actual: relation.sub_type
1980
+ )
1762
1981
  end
1982
+ end
1763
1983
 
1764
- if method_type.block && block_params
1765
- block_annotations = source.annotations(block: node)
1984
+ if block_params && method_type.block
1985
+ block_annotations = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
1986
+ block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
1987
+ block_param_hint = block_params_.params_type(hint: method_type.block.type.params)
1766
1988
 
1767
- params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
1768
- block_param_pairs = params.zip(method_type.block.params)
1989
+ relation = Subtyping::Relation.new(
1990
+ sub_type: AST::Types::Proc.new(params: block_param_hint, return_type: AST::Types::Any.new),
1991
+ super_type: method_type.block.type
1992
+ )
1769
1993
 
1770
- unless block_param_pairs
1771
- return Errors::IncompatibleBlockParameters.new(
1772
- node: node,
1773
- method_type: method_type
1774
- )
1775
- end
1994
+ checker.check(relation, constraints: constraints).else do |result|
1995
+ return Errors::IncompatibleBlockParameters.new(
1996
+ node: node,
1997
+ method_type: method_type
1998
+ )
1999
+ end
2000
+ end
1776
2001
 
1777
- block_param_pairs.each do |param, type|
1778
- if param.type
1779
- relation = Subtyping::Relation.new(
1780
- sub_type: type,
1781
- super_type: absolute_type(param.type)
1782
- )
1783
-
1784
- checker.check(relation, constraints: constraints).else do |result|
1785
- return Errors::BlockParameterTypeMismatch.new(
1786
- node: param.node,
1787
- expected: type,
1788
- actual: param.type
1789
- )
2002
+ case
2003
+ when method_type.block && block_params
2004
+ Steep.logger.debug "block is okay: method_type=#{method_type}"
2005
+ Steep.logger.debug "Constraints = #{constraints}"
2006
+
2007
+ begin
2008
+ method_type.subst(constraints.solution(checker, variance: variance, variables: occurence.params)).yield_self do |method_type|
2009
+ block_type = construction.type_block(block_param_hint: method_type.block.type.params,
2010
+ block_type_hint: method_type.block.type.return_type,
2011
+ node_type_hint: method_type.return_type,
2012
+ block_params: block_params_,
2013
+ block_body: block_body,
2014
+ block_annotations: block_annotations)
2015
+
2016
+ relation = Subtyping::Relation.new(sub_type: block_type.return_type,
2017
+ super_type: method_type.block.type.return_type)
2018
+
2019
+ result = checker.check(relation, constraints: constraints)
2020
+
2021
+ case result
2022
+ when Subtyping::Result::Success
2023
+ method_type.return_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).yield_self do |ret_type|
2024
+ if block_annotations.break_type
2025
+ AST::Types::Union.new(types: [block_annotations.break_type, ret_type])
2026
+ else
2027
+ ret_type
2028
+ end
1790
2029
  end
2030
+
2031
+ when Subtyping::Result::Failure
2032
+ Errors::BlockTypeMismatch.new(node: node,
2033
+ expected: method_type.block.type,
2034
+ actual: block_type,
2035
+ result: result)
1791
2036
  end
1792
2037
  end
1793
2038
 
1794
- if block_annotations.block_type
1795
- relation = Subtyping::Relation.new(
1796
- sub_type: absolute_type(block_annotations.block_type),
1797
- super_type: method_type.block.return_type
1798
- )
1799
-
1800
- checker.check(relation, constraints: constraints).else do |result|
1801
- typing.add_error Errors::BlockTypeMismatch.new(node: node,
1802
- expected: method_type.block.return_type,
1803
- actual: absolute_type(block_annotations.block_type),
1804
- result: result)
2039
+ rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
2040
+ Errors::UnsatisfiableConstraint.new(node: node,
2041
+ method_type: method_type,
2042
+ var: exn.var,
2043
+ sub_type: exn.sub_type,
2044
+ super_type: exn.super_type,
2045
+ result: exn.result)
2046
+ end
2047
+
2048
+ when method_type.block && args.block_pass_arg
2049
+ begin
2050
+ method_type.subst(constraints.solution(checker, variance: variance, variables: occurence.params)).yield_self do |method_type|
2051
+ block_type = synthesize(args.block_pass_arg, hint: method_type.block.type)
2052
+ relation = Subtyping::Relation.new(sub_type: block_type,
2053
+ super_type: method_type.block.yield_self do |expected_block|
2054
+ if expected_block.optional?
2055
+ Types.optional(expected_block.type)
2056
+ else
2057
+ expected_block.type
2058
+ end
2059
+ end)
2060
+ result = checker.check(relation, constraints: constraints)
2061
+
2062
+ case result
2063
+ when Subtyping::Result::Success
2064
+ method_type.return_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars))
2065
+
2066
+ when Subtyping::Result::Failure
2067
+ Errors::BlockTypeMismatch.new(node: node,
2068
+ expected: method_type.block.type,
2069
+ actual: block_type,
2070
+ result: result)
1805
2071
  end
1806
2072
  end
2073
+
2074
+ rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
2075
+ Errors::UnsatisfiableConstraint.new(node: node,
2076
+ method_type: method_type,
2077
+ var: exn.var,
2078
+ sub_type: exn.sub_type,
2079
+ super_type: exn.super_type,
2080
+ result: exn.result)
1807
2081
  end
1808
2082
 
1809
- case
1810
- when method_type.block && block_params && block_body
1811
- Steep.logger.debug "block is okay: method_type=#{method_type}"
1812
- Steep.logger.debug "Constraints = #{constraints}"
2083
+ when (!method_type.block || method_type.block.optional?) && !block_params && !block_body && !args.block_pass_arg
2084
+ # OK, without block
2085
+ method_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).return_type
1813
2086
 
1814
- begin
1815
- method_type.subst(constraints.solution(checker, variance: variance, variables: occurence.params)).yield_self do |method_type|
1816
- block_annotations = source.annotations(block: node)
2087
+ when !method_type.block && (block_params || args.block_pass_arg)
2088
+ Errors::UnexpectedBlockGiven.new(
2089
+ node: node,
2090
+ method_type: method_type
2091
+ )
1817
2092
 
1818
- block_param_pairs = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations).yield_self do |params|
1819
- params.zip(method_type.block.params)
1820
- end
2093
+ when method_type.block && !method_type.block.optional? && !block_params && !block_body && !args.block_pass_arg
2094
+ Errors::RequiredBlockMissing.new(
2095
+ node: node,
2096
+ method_type: method_type
2097
+ )
1821
2098
 
1822
- for_block, return_type = for_block(block_annotations: block_annotations,
1823
- param_pairs: block_param_pairs,
1824
- method_return_type: method_type.return_type,
1825
- typing: child_typing)
2099
+ else
2100
+ raise "Unexpected case condition"
2101
+ end
2102
+ end
2103
+ end
1826
2104
 
1827
- each_child_node(block_params) do |p|
1828
- for_block.synthesize(p)
1829
- end
2105
+ def type_block(block_param_hint:, block_type_hint:, node_type_hint:, block_params:, block_body:, block_annotations:)
2106
+ block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
1830
2107
 
1831
- block_body_type = for_block.synthesize(block_body)
2108
+ param_types_hash = {}
2109
+ if block_param_pairs
2110
+ block_param_pairs.each do |param, type|
2111
+ var_name = param.var.name
2112
+ param_types_hash[var_name] = type
2113
+ end
2114
+ else
2115
+ block_params.each do |param|
2116
+ var_name = param.var.name
2117
+ param_types_hash[var_name] = param.type || Types.any
2118
+ end
2119
+ end
1832
2120
 
1833
- unless method_type.block.return_type.is_a?(AST::Types::Void)
1834
- result = checker.check(Subtyping::Relation.new(
1835
- sub_type: block_annotations.block_type || block_body_type,
1836
- super_type: method_type.block.return_type
1837
- ), constraints: constraints)
2121
+ block_type_env = type_env.dup.tap do |env|
2122
+ param_types_hash.each do |name, type|
2123
+ env.set(lvar: name, type: type)
2124
+ end
2125
+
2126
+ block_annotations.lvar_types.each do |name, type|
2127
+ env.set(lvar: name, type: type)
2128
+ end
2129
+ end
1838
2130
 
1839
- if result.success?
1840
- return_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).tap do
1841
- child_typing.save!
2131
+ break_type = if block_annotations.break_type
2132
+ union_type(node_type_hint, block_annotations.break_type)
2133
+ else
2134
+ node_type_hint
1842
2135
  end
1843
- else
1844
- typing.add_error Errors::BlockTypeMismatch.new(node: node,
1845
- expected: method_type.block.return_type,
1846
- actual: block_annotations.block_type || block_body_type,
1847
- result: result)
1848
- return_type
1849
- end
1850
- else
1851
- child_typing.save!
1852
- return_type
1853
- end
1854
- end
2136
+ Steep.logger.debug("return_type = #{break_type}")
1855
2137
 
1856
- rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
1857
- typing.add_error Errors::UnsatisfiableConstraint.new(node: node,
1858
- method_type: method_type,
1859
- var: exn.var,
1860
- sub_type: exn.sub_type,
1861
- super_type: exn.super_type,
1862
- result: exn.result
1863
- )
1864
- fallback_any_rec node
1865
- end
2138
+ block_context = BlockContext.new(body_type: block_annotations.block_type)
2139
+ Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
1866
2140
 
1867
- when !method_type.block && !block_params && !block_body
1868
- # OK, without block
1869
- method_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).return_type.tap do
1870
- child_typing.save!
1871
- end
2141
+ break_context = BreakContext.new(
2142
+ break_type: break_type,
2143
+ next_type: block_context.body_type
2144
+ )
2145
+ Steep.logger.debug("break_context { type: #{break_context.break_type} }")
1872
2146
 
1873
- when !method_type.block && block_params && block_body
1874
- Errors::UnexpectedBlockGiven.new(
1875
- node: node,
1876
- method_type: method_type
1877
- )
2147
+ for_block_body = self.class.new(
2148
+ checker: checker,
2149
+ source: source,
2150
+ annotations: annotations.merge_block_annotations(block_annotations),
2151
+ type_env: block_type_env,
2152
+ block_context: block_context,
2153
+ typing: typing,
2154
+ method_context: method_context,
2155
+ module_context: module_context,
2156
+ self_type: block_annotations.self_type || self_type,
2157
+ break_context: break_context
2158
+ )
1878
2159
 
1879
- when method_type.block && !block_params && !block_body
1880
- Errors::RequiredBlockMissing.new(
1881
- node: node,
1882
- method_type: method_type
1883
- )
2160
+ if block_body
2161
+ return_type = if (body_type = block_context.body_type)
2162
+ for_block_body.check(block_body, body_type) do |expected, actual, result|
2163
+ typing.add_error Errors::BlockTypeMismatch.new(node: block_body,
2164
+ expected: expected,
2165
+ actual: actual,
2166
+ result: result)
1884
2167
 
1885
- else
1886
- raise "Unexpected case condition"
1887
- end
1888
- end
2168
+ end
2169
+ body_type
2170
+ else
2171
+ for_block_body.synthesize(block_body, hint: block_type_hint)
2172
+ end
2173
+ else
2174
+ return_type = Types.any
2175
+ end
2176
+
2177
+ AST::Types::Proc.new(
2178
+ params: block_param_hint || block_params.params_type,
2179
+ return_type: return_type
2180
+ ).tap do |type|
2181
+ Steep.logger.debug "block_type == #{type}"
1889
2182
  end
1890
2183
  end
1891
2184
 
@@ -2137,7 +2430,7 @@ module Steep
2137
2430
  case
2138
2431
  when module_context.defined_instance_methods.include?(method_name)
2139
2432
  # ok
2140
- when annotations.dynamics[method_name]&.instance_method?
2433
+ when annotations.instance_dynamics.include?(method_name)
2141
2434
  # ok
2142
2435
  else
2143
2436
  typing.add_error Errors::MethodDefinitionMissing.new(node: node,
@@ -2150,7 +2443,7 @@ module Steep
2150
2443
  case
2151
2444
  when module_context.defined_module_methods.include?(method_name)
2152
2445
  # ok
2153
- when annotations.dynamics[method_name]&.module_method?
2446
+ when annotations.module_dynamics.include?(method_name)
2154
2447
  # ok
2155
2448
  else
2156
2449
  typing.add_error Errors::MethodDefinitionMissing.new(node: node,
@@ -2160,13 +2453,15 @@ module Steep
2160
2453
  end
2161
2454
  end
2162
2455
 
2163
- annotations.dynamics.each do |method_name, annotation|
2164
- case
2165
- when annotation.module_method? && expected_module_method_names.member?(method_name)
2166
- # ok
2167
- when annotation.instance_method? && expected_instance_method_names.member?(method_name)
2168
- # ok
2169
- else
2456
+ annotations.instance_dynamics.each do |method_name|
2457
+ unless expected_instance_method_names.member?(method_name)
2458
+ typing.add_error Errors::UnexpectedDynamicMethod.new(node: node,
2459
+ module_name: module_name.name,
2460
+ method_name: method_name)
2461
+ end
2462
+ end
2463
+ annotations.module_dynamics.each do |method_name|
2464
+ unless expected_module_method_names.member?(method_name)
2170
2465
  typing.add_error Errors::UnexpectedDynamicMethod.new(node: node,
2171
2466
  module_name: module_name.name,
2172
2467
  method_name: method_name)
@@ -2234,13 +2529,15 @@ module Steep
2234
2529
  typing.type_of(node: node)
2235
2530
  end
2236
2531
 
2237
- def self.unwrap(type)
2238
- case
2239
- when type.is_a?(AST::Types::Union)
2240
- types = type.types.reject {|type| type.is_a?(AST::Types::Nil) }
2241
- AST::Types::Union.build(types: types)
2242
- else
2243
- type
2532
+ def unwrap(type)
2533
+ expand_alias(type) do |expanded|
2534
+ case
2535
+ when expanded.is_a?(AST::Types::Union)
2536
+ types = expanded.types.reject {|type| type.is_a?(AST::Types::Nil) }
2537
+ AST::Types::Union.build(types: types)
2538
+ else
2539
+ type
2540
+ end
2244
2541
  end
2245
2542
  end
2246
2543
 
@@ -2272,6 +2569,18 @@ module Steep
2272
2569
  end
2273
2570
  end
2274
2571
 
2572
+ def expand_alias(type)
2573
+ if type
2574
+ expanded = checker.expand_alias(type)
2575
+ end
2576
+
2577
+ if block_given?
2578
+ yield expanded, type
2579
+ else
2580
+ expanded
2581
+ end
2582
+ end
2583
+
2275
2584
  def test_literal_type(literal, hint)
2276
2585
  case hint
2277
2586
  when AST::Types::Literal
@@ -2284,5 +2593,26 @@ module Steep
2284
2593
  end
2285
2594
  end
2286
2595
  end
2596
+
2597
+ def select_super_type(sub_type, super_type)
2598
+ if super_type
2599
+ result = checker.check(
2600
+ Subtyping::Relation.new(sub_type: sub_type, super_type: super_type),
2601
+ constraints: Subtyping::Constraints.empty
2602
+ )
2603
+
2604
+ if result.success?
2605
+ super_type
2606
+ else
2607
+ if block_given?
2608
+ yield result
2609
+ else
2610
+ sub_type
2611
+ end
2612
+ end
2613
+ else
2614
+ sub_type
2615
+ end
2616
+ end
2287
2617
  end
2288
2618
  end