steep 1.1.1 → 1.2.0.pre.1

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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +12 -11
  5. data/Gemfile.steep +1 -1
  6. data/Gemfile.steep.lock +9 -9
  7. data/README.md +3 -3
  8. data/Steepfile +23 -0
  9. data/bin/steep-prof +2 -1
  10. data/lib/steep/annotation_parser.rb +1 -1
  11. data/lib/steep/ast/types/class.rb +4 -0
  12. data/lib/steep/ast/types/factory.rb +86 -602
  13. data/lib/steep/ast/types/instance.rb +4 -0
  14. data/lib/steep/ast/types/literal.rb +1 -1
  15. data/lib/steep/ast/types/proc.rb +22 -8
  16. data/lib/steep/ast/types/self.rb +4 -0
  17. data/lib/steep/ast/types/union.rb +1 -1
  18. data/lib/steep/cli.rb +24 -1
  19. data/lib/steep/diagnostic/ruby.rb +17 -22
  20. data/lib/steep/drivers/checkfile.rb +205 -0
  21. data/lib/steep/drivers/validate.rb +3 -1
  22. data/lib/steep/equatable.rb +2 -0
  23. data/lib/steep/interface/block.rb +21 -11
  24. data/lib/steep/interface/builder.rb +756 -0
  25. data/lib/steep/interface/function.rb +32 -24
  26. data/lib/steep/interface/method_type.rb +191 -78
  27. data/lib/steep/interface/shape.rb +132 -0
  28. data/lib/steep/interface/substitution.rb +23 -12
  29. data/lib/steep/interface/type_param.rb +1 -2
  30. data/lib/steep/path_helper.rb +1 -1
  31. data/lib/steep/project.rb +5 -7
  32. data/lib/steep/server/base_worker.rb +2 -2
  33. data/lib/steep/server/change_buffer.rb +4 -3
  34. data/lib/steep/server/interaction_worker.rb +1 -1
  35. data/lib/steep/server/master.rb +69 -9
  36. data/lib/steep/server/type_check_worker.rb +13 -11
  37. data/lib/steep/server/worker_process.rb +9 -7
  38. data/lib/steep/services/completion_provider.rb +15 -3
  39. data/lib/steep/services/hover_provider/singleton_methods.rb +5 -6
  40. data/lib/steep/services/signature_service.rb +13 -8
  41. data/lib/steep/services/type_check_service.rb +2 -0
  42. data/lib/steep/signature/validator.rb +1 -1
  43. data/lib/steep/subtyping/check.rb +154 -103
  44. data/lib/steep/subtyping/relation.rb +3 -3
  45. data/lib/steep/subtyping/result.rb +20 -2
  46. data/lib/steep/subtyping/variable_variance.rb +9 -0
  47. data/lib/steep/type_construction.rb +558 -299
  48. data/lib/steep/type_inference/block_params.rb +169 -86
  49. data/lib/steep/type_inference/logic_type_interpreter.rb +9 -14
  50. data/lib/steep/type_inference/method_params.rb +12 -7
  51. data/lib/steep/type_inference/send_args.rb +41 -35
  52. data/lib/steep/type_inference/type_env_builder.rb +1 -1
  53. data/lib/steep/version.rb +1 -1
  54. data/lib/steep.rb +71 -2
  55. data/rbs_collection.steep.lock.yaml +18 -30
  56. data/rbs_collection.steep.yaml +1 -0
  57. data/sig/shims/language-server_protocol.rbs +20 -0
  58. data/sig/shims/tagged_logging.rbs +6 -0
  59. data/sig/steep/ast/annotation/collection.rbs +6 -6
  60. data/sig/steep/ast/types/class.rbs +3 -0
  61. data/sig/steep/ast/types/factory.rbs +38 -32
  62. data/sig/steep/ast/types/instance.rbs +3 -0
  63. data/sig/steep/ast/types/intersection.rbs +1 -1
  64. data/sig/steep/ast/types/literal.rbs +7 -7
  65. data/sig/steep/ast/types/name.rbs +14 -13
  66. data/sig/steep/ast/types/proc.rbs +3 -1
  67. data/sig/steep/ast/types/self.rbs +3 -0
  68. data/sig/steep/ast/types/var.rbs +1 -1
  69. data/sig/steep/diagnostic/ruby.rbs +30 -34
  70. data/sig/steep/drivers/annotations.rbs +17 -0
  71. data/sig/steep/drivers/check.rbs +33 -0
  72. data/sig/steep/drivers/checkfile.rbs +26 -0
  73. data/sig/steep/drivers/diagnostic_printer.rbs +25 -0
  74. data/sig/steep/drivers/init.rbs +19 -0
  75. data/sig/steep/drivers/langserver.rbs +35 -0
  76. data/sig/steep/drivers/print_project.rbs +15 -0
  77. data/sig/steep/drivers/stats.rbs +37 -0
  78. data/sig/steep/drivers/utils/driver_helper.rbs +23 -0
  79. data/sig/steep/drivers/utils/jobs_count.rbs +11 -0
  80. data/sig/steep/drivers/validate.rbs +15 -0
  81. data/sig/steep/drivers/vendor.rbs +19 -0
  82. data/sig/steep/drivers/watch.rbs +27 -0
  83. data/sig/steep/drivers/worker.rbs +31 -0
  84. data/sig/steep/equatable.rbs +11 -0
  85. data/sig/steep/index/rbs_index.rbs +91 -0
  86. data/sig/steep/index/signature_symbol_provider.rbs +29 -0
  87. data/sig/steep/index/source_index.rbs +63 -0
  88. data/sig/steep/interface/block.rbs +3 -1
  89. data/sig/steep/interface/builder.rbs +152 -0
  90. data/sig/steep/interface/function.rbs +67 -55
  91. data/sig/steep/interface/method_type.rbs +60 -12
  92. data/sig/steep/interface/shape.rbs +61 -0
  93. data/sig/steep/interface/substitution.rbs +18 -22
  94. data/sig/steep/interface/type_param.rbs +9 -1
  95. data/sig/steep/path_helper.rbs +7 -0
  96. data/sig/steep/project/pattern.rbs +10 -10
  97. data/sig/steep/project/target.rbs +2 -2
  98. data/sig/steep/project.rbs +15 -8
  99. data/sig/steep/server/base_worker.rbs +49 -0
  100. data/sig/steep/server/change_buffer.rbs +32 -0
  101. data/sig/steep/server/interaction_worker.rbs +41 -0
  102. data/sig/steep/server/lsp_formatter.rbs +29 -0
  103. data/sig/steep/server/master.rbs +260 -0
  104. data/sig/steep/server/type_check_worker.rbs +135 -0
  105. data/sig/steep/server/worker_process.rbs +29 -0
  106. data/sig/steep/services/completion_provider.rbs +5 -5
  107. data/sig/steep/services/content_change.rbs +14 -12
  108. data/sig/steep/services/file_loader.rbs +12 -4
  109. data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
  110. data/sig/steep/services/path_assignment.rbs +7 -7
  111. data/sig/steep/services/signature_service.rbs +67 -40
  112. data/sig/steep/services/type_check_service.rbs +53 -39
  113. data/sig/steep/subtyping/check.rbs +80 -44
  114. data/sig/steep/subtyping/relation.rbs +24 -22
  115. data/sig/steep/subtyping/result.rbs +48 -30
  116. data/sig/steep/subtyping/variable_variance.rbs +2 -0
  117. data/sig/steep/type_construction.rbs +132 -23
  118. data/sig/steep/type_inference/block_params.rbs +120 -18
  119. data/sig/steep/type_inference/context.rbs +45 -20
  120. data/sig/steep/type_inference/context_array.rbs +37 -0
  121. data/sig/steep/type_inference/logic_type_interpreter.rbs +3 -1
  122. data/sig/steep/type_inference/method_params.rbs +13 -9
  123. data/sig/steep/type_inference/send_args.rbs +229 -0
  124. data/sig/steep/type_inference/type_env_builder.rbs +1 -1
  125. data/sig/steep/typing.rbs +4 -4
  126. data/sig/steep.rbs +4 -2
  127. data/smoke/block/e.rb +12 -0
  128. data/smoke/block/e.rbs +4 -0
  129. data/smoke/block/test_expectations.yml +12 -0
  130. data/smoke/regression/block_param_split.rb +7 -0
  131. data/smoke/regression/block_param_split.rbs +3 -0
  132. data/smoke/regression/empty_yield.rb +5 -0
  133. data/smoke/regression/empty_yield.rbs +3 -0
  134. data/smoke/regression/test_expectations.yml +12 -0
  135. data/smoke/yield/test_expectations.yml +4 -4
  136. data/steep.gemspec +2 -1
  137. metadata +61 -9
  138. data/lib/steep/interface/interface.rb +0 -34
  139. data/sig/steep/interface/interface.rbs +0 -23
  140. data/sig/version.rbs +0 -3
@@ -146,7 +146,7 @@ module Steep
146
146
  definition_method_type = if definition
147
147
  definition.methods[method_name]&.yield_self do |method|
148
148
  method.method_types
149
- .map {|method_type| checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]) }
149
+ .map {|method_type| checker.factory.method_type(method_type, method_decls: Set[]) }
150
150
  .select {|method_type| method_type.is_a?(Interface::MethodType) }
151
151
  .inject {|t1, t2| t1 + t2}
152
152
  end
@@ -347,6 +347,8 @@ module Steep
347
347
  if implement_module_name
348
348
  module_entry = checker.factory.definition_builder.env.class_decls[implement_module_name.name]
349
349
 
350
+ raise unless module_entry.is_a?(RBS::Environment::ModuleEntry)
351
+
350
352
  module_context = module_context.update(
351
353
  instance_type: AST::Types::Intersection.build(
352
354
  types: [
@@ -534,6 +536,15 @@ module Steep
534
536
  end
535
537
  end
536
538
 
539
+ def meta_type(type)
540
+ case type
541
+ when AST::Types::Name::Instance
542
+ type.to_module
543
+ when AST::Types::Name::Singleton
544
+ AST::Builtin::Class.instance_type
545
+ end
546
+ end
547
+
537
548
  def for_sclass(node, type)
538
549
  annots = source.annotations(block: node, factory: checker.factory, context: nesting)
539
550
 
@@ -605,7 +616,7 @@ module Steep
605
616
  block_context: nil,
606
617
  module_context: module_context,
607
618
  break_context: nil,
608
- self_type: module_context.module_type,
619
+ self_type: meta_type(annots.self_type || type) || AST::Builtin::Class.module_type,
609
620
  type_env: type_env,
610
621
  call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
611
622
  variable_context: TypeInference::Context::TypeVariableContext.empty # Assuming `::Class` and `::Module` don't have type params
@@ -885,14 +896,14 @@ module Steep
885
896
  synthesize(child)
886
897
  end
887
898
 
888
- super_method = Interface::Interface::Entry.new(
899
+ super_method = Interface::Shape::Entry.new(
889
900
  method_types: method_context.super_method.method_types.map {|method_type|
890
901
  decl = TypeInference::MethodCall::MethodDecl.new(
891
902
  method_name: InstanceMethodName.new(type_name: super_def.implemented_in || super_def.defined_in,
892
903
  method_name: method_context.name),
893
904
  method_def: super_def
894
905
  )
895
- checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[decl])
906
+ checker.factory.method_type(method_type, method_decls: Set[decl])
896
907
  }
897
908
  )
898
909
 
@@ -1598,22 +1609,29 @@ module Steep
1598
1609
  end
1599
1610
 
1600
1611
  when :yield
1601
- if method_context&.method_type
1602
- if method_context.block_type
1603
- block_type = method_context.block_type
1604
- block_type.type.params.flat_unnamed_params.map(&:last).zip(node.children).each do |(type, node)|
1605
- if node && type
1606
- check(node, type) do |_, rhs_type, result|
1607
- typing.add_error(
1608
- Diagnostic::Ruby::IncompatibleAssignment.new(
1609
- node: node,
1610
- lhs_type: type,
1611
- rhs_type: rhs_type,
1612
- result: result
1613
- )
1614
- )
1615
- end
1616
- end
1612
+ if method_context && method_context.method_type
1613
+ if block_type = method_context.block_type
1614
+ type = AST::Types::Proc.new(
1615
+ type: block_type.type,
1616
+ block: nil,
1617
+ self_type: block_type.self_type
1618
+ )
1619
+ args = TypeInference::SendArgs.new(
1620
+ node: node,
1621
+ arguments: node.children,
1622
+ type: type
1623
+ )
1624
+
1625
+ # @type var errors: Array[Diagnostic::Ruby::Base]
1626
+ errors = []
1627
+ constr = type_check_args(
1628
+ args,
1629
+ Subtyping::Constraints.new(unknowns: []),
1630
+ errors
1631
+ )
1632
+
1633
+ errors.each do |error|
1634
+ typing.add_error(error)
1617
1635
  end
1618
1636
 
1619
1637
  add_typing(node, type: block_type.type.return_type)
@@ -1630,11 +1648,10 @@ module Steep
1630
1648
  if method_context&.method
1631
1649
  if method_context.super_method
1632
1650
  types = method_context.super_method.method_types.map {|method_type|
1633
- checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]).type.return_type
1651
+ checker.factory.method_type(method_type, method_decls: Set[]).type.return_type
1634
1652
  }
1635
1653
  add_typing(node, type: union_type(*types))
1636
1654
  else
1637
-
1638
1655
  fallback_to_any(node) do
1639
1656
  Diagnostic::Ruby::UnexpectedSuper.new(node: node, method: method_context.name)
1640
1657
  end
@@ -1692,7 +1709,7 @@ module Steep
1692
1709
 
1693
1710
  left_type, constr, left_context = synthesize(left_node, hint: hint, condition: true).to_ary
1694
1711
 
1695
- interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1712
+ interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing, config: builder_config)
1696
1713
  left_truthy_env, left_falsy_env = interpreter.eval(env: left_context.type_env, node: left_node)
1697
1714
 
1698
1715
  if left_type.is_a?(AST::Types::Logic::Env)
@@ -1740,7 +1757,7 @@ module Steep
1740
1757
 
1741
1758
  left_type, constr, left_context = synthesize(left_node, hint: hint, condition: true).to_ary
1742
1759
 
1743
- interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1760
+ interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing, config: builder_config)
1744
1761
  left_truthy_env, left_falsy_env = interpreter.eval(env: left_context.type_env, node: left_node)
1745
1762
 
1746
1763
  if left_type.is_a?(AST::Types::Logic::Env)
@@ -1787,7 +1804,7 @@ module Steep
1787
1804
  cond, true_clause, false_clause = node.children
1788
1805
 
1789
1806
  cond_type, constr = synthesize(cond, condition: true).to_ary
1790
- interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: constr.typing)
1807
+ interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: constr.typing, config: builder_config)
1791
1808
  truthy_env, falsy_env = interpreter.eval(env: constr.context.type_env, node: cond)
1792
1809
 
1793
1810
  if true_clause
@@ -1830,7 +1847,7 @@ module Steep
1830
1847
  env.join(*envs)
1831
1848
  end
1832
1849
 
1833
- node_type = union_type(true_pair&.type || AST::Builtin.nil_type, false_pair&.type || AST::Builtin.nil_type)
1850
+ node_type = union_type_unify(true_pair&.type || AST::Builtin.nil_type, false_pair&.type || AST::Builtin.nil_type)
1834
1851
  add_typing(node, type: node_type, constr: constr)
1835
1852
  end
1836
1853
 
@@ -1839,7 +1856,7 @@ module Steep
1839
1856
  cond, *whens, els = node.children
1840
1857
 
1841
1858
  constr = self
1842
- interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1859
+ interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing, config: builder_config)
1843
1860
 
1844
1861
  if cond
1845
1862
  branch_results = []
@@ -1971,7 +1988,7 @@ module Steep
1971
1988
  env.join(*envs)
1972
1989
  end
1973
1990
 
1974
- add_typing(node, type: union_type(*types), constr: constr)
1991
+ add_typing(node, type: union_type_unify(*types), constr: constr)
1975
1992
  end
1976
1993
 
1977
1994
  when :rescue
@@ -2085,16 +2102,19 @@ module Steep
2085
2102
  collection_type, constr, collection_context = synthesize(collection).to_ary
2086
2103
  collection_type = expand_self(collection_type)
2087
2104
 
2088
- var_type = case collection_type
2089
- when AST::Types::Any
2090
- AST::Types::Any.new
2091
- else
2092
- each = calculate_interface(collection_type, private: true).methods[:each]
2093
- method_type = (each&.method_types || []).find {|type| type.block && type.block.type.params.first_param }
2094
- method_type&.yield_self do |method_type|
2095
- method_type.block.type.params.first_param&.type
2096
- end
2097
- end
2105
+ if collection_type.is_a?(AST::Types::Any)
2106
+ var_type = AST::Builtin.any_type
2107
+ else
2108
+ if each = calculate_interface(collection_type, :each, private: true)
2109
+ if method_type = (each.method_types || []).find {|type| type.block && type.block.type.params.first_param }
2110
+ if block = method_type.block
2111
+ if first_param = block.type.params.first_param
2112
+ var_type = first_param.type
2113
+ end
2114
+ end
2115
+ end
2116
+ end
2117
+ end
2098
2118
  var_name = asgn.children[0]
2099
2119
 
2100
2120
  if var_type
@@ -2133,7 +2153,7 @@ module Steep
2133
2153
  cond, body = node.children
2134
2154
  cond_type, constr = synthesize(cond, condition: true).to_ary
2135
2155
 
2136
- interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
2156
+ interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing, config: builder_config)
2137
2157
  truthy_env, falsy_env = interpreter.eval(env: constr.context.type_env, node: cond)
2138
2158
 
2139
2159
  case node.type
@@ -2307,9 +2327,7 @@ module Steep
2307
2327
  when AST::Types::Any
2308
2328
  type = AST::Types::Any.new
2309
2329
  else
2310
- interface = calculate_interface(param_type, private: true)
2311
- method = interface.methods[value.children[0]]
2312
- if method
2330
+ if method = calculate_interface(param_type, private: true)&.methods&.[](value.children[0])
2313
2331
  return_types = method.method_types.filter_map do |method_type|
2314
2332
  if method_type.type.params.optional?
2315
2333
  method_type.type.return_type
@@ -2325,7 +2343,8 @@ module Steep
2325
2343
  return_type: return_types[0],
2326
2344
  location: nil
2327
2345
  ),
2328
- block: nil
2346
+ block: nil,
2347
+ self_type: nil
2329
2348
  )
2330
2349
  end
2331
2350
  end
@@ -2337,7 +2356,8 @@ module Steep
2337
2356
  type = AST::Types::Proc.new(
2338
2357
  type: method_context.method_type.block.type,
2339
2358
  location: nil,
2340
- block: nil
2359
+ block: nil,
2360
+ self_type: method_context.method_type.block.self_type
2341
2361
  )
2342
2362
  if method_context.method_type.block.optional?
2343
2363
  type = AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
@@ -2570,7 +2590,11 @@ module Steep
2570
2590
  type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
2571
2591
  end
2572
2592
 
2573
- truthy_rhs_type = AST::Types::Union.build(types: truthys)
2593
+ truthy_rhs_type = union_type_unify(*truthys)
2594
+ if truthy_rhs_type.is_a?(AST::Types::Union)
2595
+ tup = union_of_tuple_to_tuple_of_union(truthy_rhs_type)
2596
+ truthy_rhs_type = tup if tup
2597
+ end
2574
2598
  optional = !falsys.empty?
2575
2599
 
2576
2600
  if truthy_rhs_type.is_a?(AST::Types::Tuple) || AST::Builtin::Array.instance_type?(truthy_rhs_type) || truthy_rhs_type.is_a?(AST::Types::Any)
@@ -2707,6 +2731,7 @@ module Steep
2707
2731
  params_hint = type_hint.type.params
2708
2732
  return_hint = type_hint.type.return_type
2709
2733
  block_hint = type_hint.block
2734
+ self_hint = type_hint.self_type
2710
2735
  end
2711
2736
 
2712
2737
  block_constr = for_block(
@@ -2716,6 +2741,7 @@ module Steep
2716
2741
  block_type_hint: return_hint,
2717
2742
  block_block_hint: block_hint,
2718
2743
  block_annotations: block_annotations,
2744
+ block_self_hint: self_hint,
2719
2745
  node_type_hint: nil
2720
2746
  )
2721
2747
 
@@ -2730,10 +2756,10 @@ module Steep
2730
2756
  if block_param_type = block_param.type
2731
2757
  case block_param_type
2732
2758
  when AST::Types::Proc
2733
- Interface::Block.new(type: block_param_type.type, optional: false)
2759
+ Interface::Block.new(type: block_param_type.type, optional: false, self_type: block_param_type.self_type)
2734
2760
  else
2735
2761
  if proc_type = optional_proc?(block_param_type)
2736
- Interface::Block.new(type: proc_type.type, optional: true)
2762
+ Interface::Block.new(type: proc_type.type, optional: true, self_type: proc_type.self_type)
2737
2763
  else
2738
2764
  block_constr.typing.add_error(
2739
2765
  Diagnostic::Ruby::ProcTypeExpected.new(
@@ -2748,7 +2774,8 @@ module Steep
2748
2774
  return_type: AST::Builtin.any_type,
2749
2775
  location: nil
2750
2776
  ),
2751
- optional: false
2777
+ optional: false,
2778
+ self_type: nil
2752
2779
  )
2753
2780
  end
2754
2781
  end
@@ -2764,6 +2791,10 @@ module Steep
2764
2791
  block_type_hint: return_hint
2765
2792
  )
2766
2793
 
2794
+ return_type = return_type.subst(
2795
+ Interface::Substitution.build([], [], self_type: block_constr.self_type)
2796
+ )
2797
+
2767
2798
  if expected_block_type = block_constr.block_context.body_type
2768
2799
  type_vars = expected_block_type.free_variables
2769
2800
  subst = Interface::Substitution.build(type_vars, type_vars.map { AST::Builtin.any_type })
@@ -2792,7 +2823,8 @@ module Steep
2792
2823
  return_type: return_type,
2793
2824
  location: nil
2794
2825
  ),
2795
- block: block
2826
+ block: block,
2827
+ self_type: block_annotations.self_type || self_hint
2796
2828
  )
2797
2829
 
2798
2830
  add_typing node, type: block_type
@@ -2827,7 +2859,7 @@ module Steep
2827
2859
  end
2828
2860
 
2829
2861
  def type_send_interface(node, interface:, receiver:, receiver_type:, method_name:, arguments:, block_params:, block_body:)
2830
- method = interface.methods[method_name]
2862
+ method = interface&.methods&.[](method_name)
2831
2863
 
2832
2864
  if method
2833
2865
  call, constr = type_method_call(node,
@@ -2872,19 +2904,7 @@ module Steep
2872
2904
  call = call.with_return_type(optional_type)
2873
2905
  end
2874
2906
  else
2875
- error = Diagnostic::Ruby::UnresolvedOverloading.new(
2876
- node: node,
2877
- receiver_type: receiver_type,
2878
- method_name: method_name,
2879
- method_types: method.method_types
2880
- )
2881
- call = TypeInference::MethodCall::Error.new(
2882
- node: node,
2883
- context: context.method_context,
2884
- method_name: method_name,
2885
- receiver_type: receiver_type,
2886
- errors: [error]
2887
- )
2907
+ errors = []
2888
2908
 
2889
2909
  skips = [receiver]
2890
2910
  skips << node.children[0] if node.type == :block
@@ -2898,8 +2918,24 @@ module Steep
2898
2918
  block_params: TypeInference::BlockParams.from_node(block_params, annotations: block_annotations),
2899
2919
  block_annotations: block_annotations,
2900
2920
  block_body: block_body
2901
- )
2921
+ ) do |error|
2922
+ errors << error
2923
+ end
2902
2924
  end
2925
+
2926
+ errors << Diagnostic::Ruby::UnresolvedOverloading.new(
2927
+ node: node,
2928
+ receiver_type: interface.type,
2929
+ method_name: method_name,
2930
+ method_types: method.method_types
2931
+ )
2932
+ call = TypeInference::MethodCall::Error.new(
2933
+ node: node,
2934
+ context: context.method_context,
2935
+ method_name: method_name,
2936
+ receiver_type: receiver_type,
2937
+ errors: errors
2938
+ )
2903
2939
  end
2904
2940
 
2905
2941
  constr.add_call(call)
@@ -2939,15 +2975,41 @@ module Steep
2939
2975
  context: context.method_context,
2940
2976
  method_name: method_name,
2941
2977
  receiver_type: receiver_type,
2942
- error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
2978
+ error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: interface&.type || receiver_type)
2943
2979
  )
2944
2980
  )
2945
2981
  end
2946
2982
  end
2947
2983
 
2948
2984
  def type_send(node, send_node:, block_params:, block_body:, unwrap: false)
2949
- receiver, method_name, *arguments = send_node.children
2950
- recv_type, constr = receiver ? synthesize(receiver) : [AST::Types::Self.new, self]
2985
+ # @type var constr: TypeConstruction
2986
+
2987
+ case send_node.type
2988
+ when :super, :zsuper
2989
+ receiver = nil
2990
+ method_name = method_context&.name
2991
+ arguments = send_node.children
2992
+
2993
+ if method_name.nil? || method_context&.super_method.nil?
2994
+ return fallback_to_any(send_node) do
2995
+ Diagnostic::Ruby::UnexpectedSuper.new(
2996
+ node: send_node,
2997
+ method: method_context&.name
2998
+ )
2999
+ end
3000
+ end
3001
+
3002
+ recv_type = AST::Types::Self.instance
3003
+ constr = self
3004
+ else
3005
+ receiver, method_name, *arguments = send_node.children
3006
+ if receiver
3007
+ recv_type, constr = synthesize(receiver)
3008
+ else
3009
+ recv_type = AST::Types::Self.instance
3010
+ constr = self
3011
+ end
3012
+ end
2951
3013
 
2952
3014
  if unwrap
2953
3015
  recv_type = unwrap(recv_type)
@@ -2970,16 +3032,14 @@ module Steep
2970
3032
  )
2971
3033
  )
2972
3034
 
2973
- when AST::Types::Var
2974
- if upper_bound = variable_context[receiver_type.name]
2975
- interface = calculate_interface(upper_bound, private: false)
2976
-
3035
+ else
3036
+ if interface = calculate_interface(receiver_type, private: private)
2977
3037
  constr.type_send_interface(
2978
3038
  node,
2979
3039
  interface: interface,
2980
3040
  receiver: receiver,
2981
3041
  receiver_type: receiver_type,
2982
- method_name: method_name,
3042
+ method_name: method_name,
2983
3043
  arguments: arguments,
2984
3044
  block_params: block_params,
2985
3045
  block_body: block_body
@@ -2996,85 +3056,34 @@ module Steep
2996
3056
  )
2997
3057
  )
2998
3058
  end
2999
- when AST::Types::Void, AST::Types::Bot, AST::Types::Top, AST::Types::Var
3000
- constr = constr.synthesize_children(node, skips: [receiver])
3001
- constr.add_call(
3002
- TypeInference::MethodCall::NoMethodError.new(
3003
- node: node,
3004
- context: context.method_context,
3005
- method_name: method_name,
3006
- receiver_type: receiver_type,
3007
- error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
3008
- )
3009
- )
3010
-
3011
- when AST::Types::Self
3012
- expanded_self = expand_self(receiver_type)
3013
-
3014
- if expanded_self.is_a?(AST::Types::Self)
3015
- Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
3016
-
3017
- constr = constr.synthesize_children(node, skips: [receiver])
3018
- constr.add_call(
3019
- TypeInference::MethodCall::NoMethodError.new(
3020
- node: node,
3021
- context: context.method_context,
3022
- method_name: method_name,
3023
- receiver_type: receiver_type,
3024
- error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
3025
- )
3026
- )
3027
- else
3028
- interface = calculate_interface(expanded_self,
3029
- private: private,
3030
- self_type: AST::Types::Self.new)
3031
-
3032
- if send_node.type == :super || send_node.type == :zsuper
3033
- method_name = method_context.name
3034
- unless method_context.super_method
3035
- return fallback_to_any(send_node) do
3036
- Diagnostic::Ruby::UnexpectedSuper.new(node: send_node, method: method_name)
3037
- end
3038
- end
3039
- end
3040
-
3041
- constr.type_send_interface(node,
3042
- interface: interface,
3043
- receiver: receiver,
3044
- receiver_type: expanded_self,
3045
- method_name: method_name,
3046
- arguments: arguments,
3047
- block_params: block_params,
3048
- block_body: block_body)
3049
- end
3050
-
3051
- else
3052
- interface = calculate_interface(receiver_type, private: private, self_type: receiver_type)
3053
-
3054
- constr.type_send_interface(node,
3055
- interface: interface,
3056
- receiver: receiver,
3057
- receiver_type: receiver_type,
3058
- method_name: method_name,
3059
- arguments: arguments,
3060
- block_params: block_params,
3061
- block_body: block_body)
3062
3059
  end
3063
3060
 
3064
3061
  Pair.new(type: type, constr: constr)
3065
3062
  end
3066
3063
 
3067
- def calculate_interface(type, private:, self_type: type)
3068
- case type
3069
- when AST::Types::Self
3070
- type = self_type
3071
- when AST::Types::Instance
3072
- type = module_context.instance_type
3073
- when AST::Types::Class
3074
- type = module_context.module_type
3075
- end
3064
+ def builder_config
3065
+ Interface::Builder::Config.new(
3066
+ self_type: self_type,
3067
+ class_type: module_context.module_type,
3068
+ instance_type: module_context.instance_type,
3069
+ variable_bounds: variable_context.upper_bounds
3070
+ )
3071
+ end
3072
+
3073
+ def calculate_interface(type, method_name = nil, private:)
3074
+ shape = checker.builder.shape(
3075
+ type,
3076
+ public_only: !private,
3077
+ config: builder_config
3078
+ )
3076
3079
 
3077
- checker.factory.interface(type, private: private, self_type: self_type)
3080
+ if method_name
3081
+ if shape
3082
+ shape.methods[method_name]
3083
+ end
3084
+ else
3085
+ shape
3086
+ end
3078
3087
  end
3079
3088
 
3080
3089
  def expand_self(type)
@@ -3219,7 +3228,7 @@ module Steep
3219
3228
  end
3220
3229
 
3221
3230
  def with_child_typing(range:)
3222
- constr = with_new_typing(typing.new_child(range: range))
3231
+ constr = with_new_typing(typing.new_child(range))
3223
3232
 
3224
3233
  if block_given?
3225
3234
  yield constr
@@ -3271,6 +3280,93 @@ module Steep
3271
3280
  end
3272
3281
  end
3273
3282
 
3283
+ def type_check_args(args, constraints, errors)
3284
+ # @type var constr: TypeConstruction
3285
+ constr = self
3286
+
3287
+ es = args.each do |arg|
3288
+ case arg
3289
+ when TypeInference::SendArgs::PositionalArgs::NodeParamPair
3290
+ _, constr = constr.type_check_argument(
3291
+ arg.node,
3292
+ type: arg.param.type,
3293
+ constraints: constraints,
3294
+ errors: errors
3295
+ )
3296
+
3297
+ when TypeInference::SendArgs::PositionalArgs::NodeTypePair
3298
+ _, constr = bypass_splat(arg.node) do |n|
3299
+ constr.type_check_argument(
3300
+ n,
3301
+ type: arg.node_type,
3302
+ constraints: constraints,
3303
+ report_node: arg.node,
3304
+ errors: errors
3305
+ )
3306
+ end
3307
+
3308
+ when TypeInference::SendArgs::PositionalArgs::UnexpectedArg
3309
+ _, constr = bypass_splat(arg.node) do |n|
3310
+ constr.synthesize(n)
3311
+ end
3312
+
3313
+ when TypeInference::SendArgs::PositionalArgs::SplatArg
3314
+ arg_type, _ =
3315
+ constr
3316
+ .with_child_typing(range: arg.node.loc.expression.begin_pos ... arg.node.loc.expression.end_pos)
3317
+ .try_tuple_type!(arg.node.children[0])
3318
+ arg.type = arg_type
3319
+
3320
+ when TypeInference::SendArgs::PositionalArgs::MissingArg
3321
+ # ignore
3322
+
3323
+ when TypeInference::SendArgs::KeywordArgs::ArgTypePairs
3324
+ arg.pairs.each do |pair|
3325
+ node, type = pair
3326
+ _, constr = bypass_splat(node) do |node|
3327
+ constr.type_check_argument(
3328
+ node,
3329
+ type: type,
3330
+ constraints: constraints,
3331
+ errors: errors
3332
+ )
3333
+ end
3334
+ end
3335
+
3336
+ when TypeInference::SendArgs::KeywordArgs::UnexpectedKeyword
3337
+ if arg.node.type == :pair
3338
+ arg.node.children.each do |nn|
3339
+ _, constr = constr.synthesize(nn)
3340
+ end
3341
+ else
3342
+ _, constr = bypass_splat(arg.node) do |n|
3343
+ constr.synthesize(n)
3344
+ end
3345
+ end
3346
+
3347
+ when TypeInference::SendArgs::KeywordArgs::SplatArg
3348
+ type, _ = bypass_splat(arg.node) do |sp_node|
3349
+ if sp_node.type == :hash
3350
+ pair = constr.type_hash_record(sp_node, nil) and break pair
3351
+ end
3352
+
3353
+ constr.synthesize(sp_node)
3354
+ end
3355
+
3356
+ arg.type = type
3357
+
3358
+ when TypeInference::SendArgs::KeywordArgs::MissingKeyword
3359
+ # ignore
3360
+ else
3361
+ raise arg.inspect
3362
+ end
3363
+ end
3364
+
3365
+ errors.push(*es)
3366
+
3367
+ constr
3368
+ end
3369
+
3274
3370
  def try_method_type(node, receiver_type:, method_name:, method_type:, arguments:, block_params:, block_body:, topdown_hint:)
3275
3371
  type_params, instantiation = Interface::TypeParam.rename(method_type.type_params)
3276
3372
  type_param_names = type_params.map(&:name)
@@ -3307,91 +3403,15 @@ module Steep
3307
3403
  end
3308
3404
 
3309
3405
  checker.push_variable_bounds(upper_bounds) do
3406
+ # @type var errors: Array[Diagnostic::Ruby::Base]
3310
3407
  errors = []
3311
3408
 
3312
- args = TypeInference::SendArgs.new(node: node, arguments: arguments, method_name: method_name, method_type: method_type)
3313
- es = args.each do |arg|
3314
- case arg
3315
- when TypeInference::SendArgs::PositionalArgs::NodeParamPair
3316
- _, constr = constr.type_check_argument(
3317
- arg.node,
3318
- type: arg.param.type,
3319
- receiver_type: receiver_type,
3320
- constraints: constraints,
3321
- errors: errors
3322
- )
3323
-
3324
- when TypeInference::SendArgs::PositionalArgs::NodeTypePair
3325
- _, constr = bypass_splat(arg.node) do |n|
3326
- constr.type_check_argument(
3327
- n,
3328
- type: arg.node_type,
3329
- receiver_type: receiver_type,
3330
- constraints: constraints,
3331
- report_node: arg.node,
3332
- errors: errors
3333
- )
3334
- end
3335
-
3336
- when TypeInference::SendArgs::PositionalArgs::UnexpectedArg
3337
- _, constr = bypass_splat(arg.node) do |n|
3338
- constr.synthesize(n)
3339
- end
3340
-
3341
- when TypeInference::SendArgs::PositionalArgs::SplatArg
3342
- arg_type, _ = constr
3343
- .with_child_typing(range: arg.node.loc.expression.begin_pos ... arg.node.loc.expression.end_pos)
3344
- .try_tuple_type!(arg.node.children[0])
3345
- arg.type = arg_type
3346
-
3347
- when TypeInference::SendArgs::PositionalArgs::MissingArg
3348
- # ignore
3349
-
3350
- when TypeInference::SendArgs::KeywordArgs::ArgTypePairs
3351
- arg.pairs.each do |node, type|
3352
- _, constr = bypass_splat(node) do |node|
3353
- constr.type_check_argument(
3354
- node,
3355
- type: type,
3356
- receiver_type: receiver_type,
3357
- constraints: constraints,
3358
- errors: errors
3359
- )
3360
- end
3361
- end
3362
-
3363
- when TypeInference::SendArgs::KeywordArgs::UnexpectedKeyword
3364
- if arg.node.type == :pair
3365
- arg.node.children.each do |nn|
3366
- _, constr = constr.synthesize(nn)
3367
- end
3368
- else
3369
- _, constr = bypass_splat(arg.node) do |n|
3370
- constr.synthesize(n)
3371
- end
3372
- end
3373
-
3374
- when TypeInference::SendArgs::KeywordArgs::SplatArg
3375
- type, _ = bypass_splat(arg.node) do |sp_node|
3376
- if sp_node.type == :hash
3377
- pair = constr.type_hash_record(sp_node, nil) and break pair
3378
- end
3379
-
3380
- constr.synthesize(sp_node)
3381
- end
3382
-
3383
- arg.type = type
3384
-
3385
- when TypeInference::SendArgs::KeywordArgs::MissingKeyword
3386
- # ignore
3387
- else
3388
- raise arg.inspect
3389
- end
3390
-
3391
- constr
3392
- end
3393
-
3394
- errors.push(*es)
3409
+ args = TypeInference::SendArgs.new(node: node, arguments: arguments, type: method_type)
3410
+ constr = constr.type_check_args(
3411
+ args,
3412
+ constraints,
3413
+ errors
3414
+ )
3395
3415
 
3396
3416
  if block_params
3397
3417
  # block is given
@@ -3400,9 +3420,9 @@ module Steep
3400
3420
 
3401
3421
  if method_type.block
3402
3422
  # Method accepts block
3403
- pairs = method_type.block && block_params_&.zip(method_type.block.type.params, nil)
3423
+ pairs = block_params_&.zip(method_type.block.type.params, nil, factory: checker.factory)
3404
3424
 
3405
- if pairs
3425
+ if block_params_ && pairs
3406
3426
  # Block parameters are compatible with the block type
3407
3427
  block_constr = constr.for_block(
3408
3428
  block_body,
@@ -3411,6 +3431,7 @@ module Steep
3411
3431
  block_type_hint: method_type.block.type.return_type,
3412
3432
  block_block_hint: nil,
3413
3433
  block_annotations: block_annotations,
3434
+ block_self_hint: method_type.block.self_type,
3414
3435
  node_type_hint: method_type.type.return_type
3415
3436
  )
3416
3437
  block_constr = block_constr.with_new_typing(
@@ -3420,18 +3441,39 @@ module Steep
3420
3441
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
3421
3442
 
3422
3443
  pairs.each do |param, type|
3423
- _, block_constr = block_constr.synthesize(param.node, hint: param.type || type).to_ary
3424
-
3425
- if param.type
3426
- check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
3427
- error = Diagnostic::Ruby::IncompatibleAssignment.new(
3428
- node: param.node,
3429
- lhs_type: param.type,
3430
- rhs_type: type,
3431
- result: result
3432
- )
3433
- errors << error
3444
+ case param
3445
+ when TypeInference::BlockParams::Param
3446
+ _, block_constr = block_constr.synthesize(param.node, hint: param.type || type).to_ary
3447
+
3448
+ if param.type
3449
+ check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
3450
+ error = Diagnostic::Ruby::IncompatibleAssignment.new(
3451
+ node: param.node,
3452
+ lhs_type: param.type,
3453
+ rhs_type: type,
3454
+ result: result
3455
+ )
3456
+ errors << error
3457
+ end
3434
3458
  end
3459
+ when TypeInference::BlockParams::MultipleParam
3460
+ param.each_param do |p|
3461
+ _, block_constr = block_constr.synthesize(p.node, hint: p.type || type).to_ary
3462
+
3463
+ if p.type
3464
+ check_relation(sub_type: type, super_type: p.type, constraints: constraints).else do |result|
3465
+ error = Diagnostic::Ruby::IncompatibleAssignment.new(
3466
+ node: p.node,
3467
+ lhs_type: p.type,
3468
+ rhs_type: type,
3469
+ result: result
3470
+ )
3471
+ errors << error
3472
+ end
3473
+ end
3474
+ end
3475
+
3476
+ _, block_constr = block_constr.add_typing(param.node, type: type)
3435
3477
  end
3436
3478
  end
3437
3479
 
@@ -3448,6 +3490,7 @@ module Steep
3448
3490
  block_constr = block_constr.update_type_env {|env| env.subst(s) }
3449
3491
  block_constr = block_constr.update_context {|context|
3450
3492
  context.with(
3493
+ self_type: method_type.block&.self_type || context.self_type,
3451
3494
  type_env: context.type_env.subst(s),
3452
3495
  block_context: context.block_context&.subst(s),
3453
3496
  break_context: context.break_context&.subst(s)
@@ -3460,6 +3503,18 @@ module Steep
3460
3503
  block_type_hint: method_type.block.type.return_type
3461
3504
  )
3462
3505
 
3506
+ if method_type.block && method_type.block.self_type
3507
+ block_body_type = block_body_type.subst(
3508
+ Interface::Substitution.build(
3509
+ [],
3510
+ [],
3511
+ self_type: method_type.block.self_type,
3512
+ module_type: singleton_type(method_type.block.self_type) || AST::Builtin.top_type,
3513
+ instance_type: instance_type(method_type.block.self_type) || AST::Builtin.top_type
3514
+ )
3515
+ )
3516
+ end
3517
+
3463
3518
  result = check_relation(sub_type: block_body_type,
3464
3519
  super_type: method_type.block.type.return_type,
3465
3520
  constraints: constraints)
@@ -3657,11 +3712,10 @@ module Steep
3657
3712
  end
3658
3713
  end
3659
3714
 
3660
- def type_check_argument(node, receiver_type:, type:, constraints:, report_node: node, errors:)
3715
+ def type_check_argument(node, type:, constraints:, report_node: node, errors:)
3661
3716
  check(node, type, constraints: constraints) do |expected, actual, result|
3662
3717
  errors << Diagnostic::Ruby::ArgumentTypeMismatch.new(
3663
3718
  node: report_node,
3664
- receiver_type: receiver_type,
3665
3719
  expected: expected,
3666
3720
  actual: actual,
3667
3721
  result: result
@@ -3669,14 +3723,19 @@ module Steep
3669
3723
  end
3670
3724
  end
3671
3725
 
3672
- def type_block_without_hint(node:, block_annotations:, block_params:, block_body:, &block)
3726
+ def type_block_without_hint(node:, block_annotations:, block_params:, block_body:)
3673
3727
  unless block_params
3674
- typing.add_error(
3675
- Diagnostic::Ruby::UnsupportedSyntax.new(
3676
- node: node.children[1],
3677
- message: "Unsupported block params pattern, probably masgn?"
3678
- )
3679
- )
3728
+ Diagnostic::Ruby::UnsupportedSyntax.new(
3729
+ node: node.children[1],
3730
+ message: "Unsupported block params pattern, probably masgn?"
3731
+ ).tap do |error|
3732
+ if block_given?
3733
+ yield error
3734
+ else
3735
+ typing.add_error(error)
3736
+ end
3737
+ end
3738
+
3680
3739
  block_params = TypeInference::BlockParams.new(leading_params: [], optional_params: [], rest_param: nil, trailing_params: [], block_param: nil)
3681
3740
  end
3682
3741
 
@@ -3687,44 +3746,91 @@ module Steep
3687
3746
  block_type_hint: nil,
3688
3747
  block_block_hint: nil,
3689
3748
  block_annotations: block_annotations,
3749
+ block_self_hint: nil,
3690
3750
  node_type_hint: nil
3691
3751
  )
3692
3752
 
3693
3753
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
3694
3754
 
3695
3755
  block_params.params.each do |param|
3696
- _, block_constr = block_constr.synthesize(param.node, hint: param.type)
3756
+ param.each_param do |param|
3757
+ _, block_constr = block_constr.synthesize(param.node, hint: param.type)
3758
+ end
3697
3759
  end
3698
3760
 
3699
3761
  block_type = block_constr.synthesize_block(node: node, block_type_hint: nil, block_body: block_body)
3700
3762
 
3701
3763
  if expected_block_type = block_constr.block_context.body_type
3702
3764
  block_constr.check_relation(sub_type: block_type, super_type: expected_block_type).else do |result|
3703
- block_constr.typing.add_error(
3704
- Diagnostic::Ruby::BlockBodyTypeMismatch.new(
3705
- node: node,
3706
- expected: expected_block_type,
3707
- actual: block_type,
3708
- result: result
3709
- )
3710
- )
3765
+ Diagnostic::Ruby::BlockBodyTypeMismatch.new(
3766
+ node: node,
3767
+ expected: expected_block_type,
3768
+ actual: block_type,
3769
+ result: result
3770
+ ).tap do |error|
3771
+ if block_given?
3772
+ yield error
3773
+ else
3774
+ block_constr.typing.add_error(error)
3775
+ end
3776
+ end
3711
3777
  end
3712
3778
  end
3713
3779
  end
3714
3780
 
3715
- def for_block(body_node, block_params:, block_param_hint:, block_type_hint:, block_block_hint:, block_annotations:, node_type_hint:)
3716
- block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint)
3781
+ def set_up_block_mlhs_params_env(node, type, hash, &block)
3782
+ if arrayish = try_convert_to_array(type)
3783
+ masgn = TypeInference::MultipleAssignment.new()
3784
+ assignments = masgn.expand(node, arrayish, false) or raise "#{arrayish} is expected to be array-ish"
3785
+ assignments.leading_assignments.each do |pair|
3786
+ node, type = pair
3717
3787
 
3788
+ if node.type == :arg
3789
+ hash[node.children[0]] = type
3790
+ else
3791
+ set_up_block_mlhs_params_env(node, type, hash, &block)
3792
+ end
3793
+ end
3794
+ else
3795
+ yield node, type
3796
+ end
3797
+ end
3798
+
3799
+ def for_block(body_node, block_params:, block_param_hint:, block_type_hint:, block_block_hint:, block_annotations:, node_type_hint:, block_self_hint:)
3800
+ block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint, factory: checker.factory)
3801
+
3802
+ # @type var param_types_hash: Hash[Symbol, AST::Types::t]
3718
3803
  param_types_hash = {}
3719
3804
  if block_param_pairs
3720
3805
  block_param_pairs.each do |param, type|
3721
- var_name = param.var
3722
- param_types_hash[var_name] = type
3806
+ case param
3807
+ when TypeInference::BlockParams::Param
3808
+ var_name = param.var
3809
+ param_types_hash[var_name] = type
3810
+ when TypeInference::BlockParams::MultipleParam
3811
+ set_up_block_mlhs_params_env(param.node, type, param_types_hash) do |error_node, non_array_type|
3812
+ Steep.logger.fatal { "`#{non_array_type}#to_ary` returns non-array-ish type" }
3813
+ annotation_types = param.variable_types()
3814
+ each_descendant_node(error_node) do |n|
3815
+ if n.type == :arg
3816
+ name = n.children[0]
3817
+ param_types_hash[name] = annotation_types[name] || AST::Builtin.any_type
3818
+ end
3819
+ end
3820
+ end
3821
+ end
3723
3822
  end
3724
3823
  else
3725
3824
  block_params.each do |param|
3726
- var_name = param.var
3727
- param_types_hash[var_name] = param.type || AST::Builtin.any_type
3825
+ case param
3826
+ when TypeInference::BlockParams::Param
3827
+ var_name = param.var
3828
+ param_types_hash[var_name] = param.type || AST::Builtin.any_type
3829
+ when TypeInference::BlockParams::MultipleParam
3830
+ param.each_param do |p|
3831
+ param_types_hash[p.var] = p.type || AST::Builtin.any_type
3832
+ end
3833
+ end
3728
3834
  end
3729
3835
  end
3730
3836
 
@@ -3742,6 +3848,19 @@ module Steep
3742
3848
  type_env = type_env.merge(local_variable_types: pins)
3743
3849
  type_env = type_env.merge(local_variable_types: param_types)
3744
3850
  type_env = TypeInference::TypeEnvBuilder.new(
3851
+ if self_binding = block_annotations.self_type || block_self_hint
3852
+ definition =
3853
+ case self_binding
3854
+ when AST::Types::Name::Instance
3855
+ checker.factory.definition_builder.build_instance(self_binding.name)
3856
+ when AST::Types::Name::Singleton
3857
+ checker.factory.definition_builder.build_singleton(self_binding.name)
3858
+ end
3859
+
3860
+ if definition
3861
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableDefinition.new(definition, checker.factory)
3862
+ end
3863
+ end,
3745
3864
  TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(block_annotations).merge!.on_duplicate! do |name, outer_type, inner_type|
3746
3865
  next if outer_type.is_a?(AST::Types::Var) || inner_type.is_a?(AST::Types::Var)
3747
3866
  next unless body_node
@@ -3771,7 +3890,7 @@ module Steep
3771
3890
  next_type: block_context.body_type || AST::Builtin.any_type
3772
3891
  )
3773
3892
 
3774
- self_type = self.self_type
3893
+ self_type = block_annotations.self_type || block_self_hint || self.self_type
3775
3894
  module_context = self.module_context
3776
3895
 
3777
3896
  if implements = block_annotations.implement_module_annotation
@@ -3828,6 +3947,44 @@ module Steep
3828
3947
  AST::Types::Union.build(types: types)
3829
3948
  end
3830
3949
 
3950
+ def union_type_unify(*types)
3951
+ types.inject do |type1, type2|
3952
+ unless no_subtyping?(sub_type: type1, super_type: type2)
3953
+ next type2
3954
+ end
3955
+
3956
+ unless no_subtyping?(sub_type: type2, super_type: type1)
3957
+ next type1
3958
+ end
3959
+
3960
+ union_type(type1, type2)
3961
+ end
3962
+ end
3963
+
3964
+ def union_of_tuple_to_tuple_of_union(type)
3965
+ if type.types.all? {|ty| ty.is_a?(AST::Types::Tuple) }
3966
+ # @type var tuples: Array[AST::Types::Tuple]
3967
+ tuples = _ = type.types
3968
+
3969
+ max = tuples.map {|tup| tup.types.size }.max or raise
3970
+
3971
+ # @type var tuple_types_array: Array[Array[AST::Types::t]]
3972
+ tuple_types_array = tuples.map do |tup|
3973
+ if tup.types.size == max
3974
+ tup.types
3975
+ else
3976
+ tup.types + Array.new(max - tup.types.size, AST::Builtin.nil_type)
3977
+ end
3978
+ end
3979
+
3980
+ # @type var tuple_elems_array: Array[Array[AST::Types::t]]
3981
+ tuple_elems_array = tuple_types_array.transpose
3982
+ AST::Types::Tuple.new(
3983
+ types: tuple_elems_array.map {|types| union_type_unify(*types) }
3984
+ )
3985
+ end
3986
+ end
3987
+
3831
3988
  def validate_method_definitions(node, module_name)
3832
3989
  module_name_1 = module_name.name
3833
3990
  member_decl_count = checker.factory.env.class_decls[module_name_1].decls.count {|d| d.decl.each_member.count > 0 }
@@ -3946,19 +4103,12 @@ module Steep
3946
4103
  end
3947
4104
 
3948
4105
  def unwrap(type)
3949
- expand_alias(type) do |expanded|
3950
- case
3951
- when expanded.is_a?(AST::Types::Union)
3952
- types = expanded.types.reject {|type| type.is_a?(AST::Types::Nil)}
3953
- AST::Types::Union.build(types: types)
3954
- else
3955
- type
3956
- end
3957
- end
4106
+ truthy, _ = checker.factory.unwrap_optional(type)
4107
+ truthy
3958
4108
  end
3959
4109
 
3960
- def deep_expand_alias(type, &block)
3961
- checker.factory.deep_expand_alias(type, &block)
4110
+ def deep_expand_alias(type)
4111
+ checker.factory.deep_expand_alias(type)
3962
4112
  end
3963
4113
 
3964
4114
  def flatten_union(type)
@@ -4030,44 +4180,101 @@ module Steep
4030
4180
  synthesize(node, hint: hint)
4031
4181
  end
4032
4182
 
4033
- def try_tuple_type(node, hint)
4034
- if hint
4035
- if node.children.size != hint.types.size
4036
- return
4037
- end
4038
- end
4183
+ def try_tuple_type(array_node, hint)
4184
+ raise unless array_node.type == :array
4039
4185
 
4040
4186
  constr = self
4187
+ # @type var element_types: Array[AST::Types::t]
4041
4188
  element_types = []
4042
4189
 
4043
- each_child_node(node).with_index do |child, index|
4044
- child_hint = if hint
4045
- hint.types[index]
4046
- end
4190
+ array_node.children.each_with_index do |child, index|
4191
+ return if child.type == :splat
4192
+
4193
+ child_hint =
4194
+ if hint
4195
+ hint.types[index]
4196
+ end
4197
+
4047
4198
  type, constr = constr.synthesize(child, hint: child_hint)
4048
4199
  element_types << type
4049
4200
  end
4050
4201
 
4051
- constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
4202
+ constr.add_typing(array_node, type: AST::Types::Tuple.new(types: element_types))
4052
4203
  end
4053
4204
 
4054
4205
  def try_convert(type, method)
4206
+ if shape = calculate_interface(type, private: false)
4207
+ if entry = shape.methods[method]
4208
+ method_type = entry.method_types.find do |method_type|
4209
+ method_type.type.params.optional?
4210
+ end
4211
+
4212
+ method_type.type.return_type if method_type
4213
+ end
4214
+ end
4215
+ end
4216
+
4217
+ def try_convert_to_array(type)
4218
+ if arrayish = arrayish_type?(type, untyped_is: true) || semantically_arrayish_type?(type)
4219
+ arrayish
4220
+ else
4221
+ if converted = try_convert(type, :to_ary)
4222
+ if arrayish_type?(converted, untyped_is: true) || semantically_arrayish_type?(type)
4223
+ converted
4224
+ end
4225
+ else
4226
+ AST::Types::Tuple.new(types: [type])
4227
+ end
4228
+ end
4229
+ end
4230
+
4231
+ def arrayish_type?(type, untyped_is: false)
4055
4232
  case type
4056
- when AST::Types::Any, AST::Types::Bot, AST::Types::Top, AST::Types::Var
4057
- return
4233
+ when AST::Types::Any
4234
+ if untyped_is
4235
+ type
4236
+ end
4237
+ when AST::Types::Name::Instance
4238
+ if AST::Builtin::Array.instance_type?(type)
4239
+ type
4240
+ end
4241
+ when AST::Types::Tuple
4242
+ type
4243
+ when AST::Types::Name::Alias
4244
+ if t = checker.factory.deep_expand_alias(type)
4245
+ arrayish_type?(t)
4246
+ end
4058
4247
  end
4248
+ end
4059
4249
 
4060
- interface = checker.factory.interface(type, private: false, self_type: self_type)
4061
- if entry = interface.methods[method]
4062
- method_type = entry.method_types.find do |method_type|
4063
- method_type.type.params.optional?
4250
+ def semantically_arrayish_type?(type)
4251
+ union = AST::Types::Union.build(types: flatten_union(type))
4252
+ if union.is_a?(AST::Types::Union)
4253
+ if tuple = union_of_tuple_to_tuple_of_union(union)
4254
+ return tuple
4064
4255
  end
4256
+ end
4257
+
4258
+ var = AST::Types::Var.fresh(:Elem)
4259
+ array = AST::Builtin::Array.instance_type(var)
4260
+ constraints = Subtyping::Constraints.new(unknowns: [])
4261
+ constraints.add_var(var.name)
4065
4262
 
4066
- method_type.type.return_type if method_type
4263
+ if (result = check_relation(sub_type: type, super_type: array, constraints: constraints)).success?
4264
+ context = Subtyping::Constraints::Context.new(
4265
+ variance: Subtyping::VariableVariance.from_type(union_type(type, var)),
4266
+ self_type: self_type,
4267
+ instance_type: module_context.instance_type,
4268
+ class_type: module_context.module_type
4269
+ )
4270
+ subst = constraints.solution(
4271
+ checker,
4272
+ variables: type.free_variables + [var.name],
4273
+ context: context
4274
+ )
4275
+
4276
+ type.subst(subst)
4067
4277
  end
4068
- rescue => exn
4069
- Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
4070
- nil
4071
4278
  end
4072
4279
 
4073
4280
  def try_array_type(node, hint)
@@ -4085,6 +4292,7 @@ module Steep
4085
4292
 
4086
4293
  case
4087
4294
  when AST::Builtin::Array.instance_type?(type)
4295
+ type.is_a?(AST::Types::Name::Instance) or raise
4088
4296
  element_types << type.args[0]
4089
4297
  when type.is_a?(AST::Types::Tuple)
4090
4298
  element_types.push(*type.types)
@@ -4284,5 +4492,56 @@ module Steep
4284
4492
  end
4285
4493
  end
4286
4494
  end
4495
+
4496
+ def type_name(type)
4497
+ case type
4498
+ when AST::Types::Name::Instance, AST::Types::Name::Singleton
4499
+ type.name
4500
+ when AST::Types::Literal
4501
+ type_name(type.back_type)
4502
+ when AST::Types::Tuple
4503
+ AST::Builtin::Array.module_name
4504
+ when AST::Types::Record
4505
+ AST::Builtin::Hash.module_name
4506
+ when AST::Types::Proc
4507
+ AST::Builtin::Proc.module_name
4508
+ when AST::Types::Boolean, AST::Types::Logic::Base
4509
+ nil
4510
+ end
4511
+ end
4512
+
4513
+ def singleton_type(type)
4514
+ case type
4515
+ when AST::Types::Union
4516
+ AST::Types::Union.build(
4517
+ types: type.types.map {|t| singleton_type(t) or return }
4518
+ )
4519
+ when AST::Types::Intersection
4520
+ AST::Types::Intersection.build(
4521
+ types: type.types.map {|t| singleton_type(t) or return }
4522
+ )
4523
+ else
4524
+ if name = type_name(type)
4525
+ AST::Types::Name::Singleton.new(name: name)
4526
+ end
4527
+ end
4528
+ end
4529
+
4530
+ def instance_type(type)
4531
+ case type
4532
+ when AST::Types::Union
4533
+ AST::Types::Union.build(
4534
+ types: type.types.map {|t| instance_type(t) or return }
4535
+ )
4536
+ when AST::Types::Intersection
4537
+ AST::Types::Intersection.build(
4538
+ types: type.types.map {|t| instance_type(t) or return }
4539
+ )
4540
+ else
4541
+ if name = type_name(type)
4542
+ checker.factory.instance_type(name)
4543
+ end
4544
+ end
4545
+ end
4287
4546
  end
4288
4547
  end