steep 0.4.0 → 0.5.0

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