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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +12 -11
- data/Gemfile.steep +1 -1
- data/Gemfile.steep.lock +9 -9
- data/README.md +3 -3
- data/Steepfile +23 -0
- data/bin/steep-prof +2 -1
- data/lib/steep/annotation_parser.rb +1 -1
- data/lib/steep/ast/types/class.rb +4 -0
- data/lib/steep/ast/types/factory.rb +86 -602
- data/lib/steep/ast/types/instance.rb +4 -0
- data/lib/steep/ast/types/literal.rb +1 -1
- data/lib/steep/ast/types/proc.rb +22 -8
- data/lib/steep/ast/types/self.rb +4 -0
- data/lib/steep/ast/types/union.rb +1 -1
- data/lib/steep/cli.rb +24 -1
- data/lib/steep/diagnostic/ruby.rb +17 -22
- data/lib/steep/drivers/checkfile.rb +205 -0
- data/lib/steep/drivers/validate.rb +3 -1
- data/lib/steep/equatable.rb +2 -0
- data/lib/steep/interface/block.rb +21 -11
- data/lib/steep/interface/builder.rb +756 -0
- data/lib/steep/interface/function.rb +32 -24
- data/lib/steep/interface/method_type.rb +191 -78
- data/lib/steep/interface/shape.rb +132 -0
- data/lib/steep/interface/substitution.rb +23 -12
- data/lib/steep/interface/type_param.rb +1 -2
- data/lib/steep/path_helper.rb +1 -1
- data/lib/steep/project.rb +5 -7
- data/lib/steep/server/base_worker.rb +2 -2
- data/lib/steep/server/change_buffer.rb +4 -3
- data/lib/steep/server/interaction_worker.rb +1 -1
- data/lib/steep/server/master.rb +69 -9
- data/lib/steep/server/type_check_worker.rb +13 -11
- data/lib/steep/server/worker_process.rb +9 -7
- data/lib/steep/services/completion_provider.rb +15 -3
- data/lib/steep/services/hover_provider/singleton_methods.rb +5 -6
- data/lib/steep/services/signature_service.rb +13 -8
- data/lib/steep/services/type_check_service.rb +2 -0
- data/lib/steep/signature/validator.rb +1 -1
- data/lib/steep/subtyping/check.rb +154 -103
- data/lib/steep/subtyping/relation.rb +3 -3
- data/lib/steep/subtyping/result.rb +20 -2
- data/lib/steep/subtyping/variable_variance.rb +9 -0
- data/lib/steep/type_construction.rb +558 -299
- data/lib/steep/type_inference/block_params.rb +169 -86
- data/lib/steep/type_inference/logic_type_interpreter.rb +9 -14
- data/lib/steep/type_inference/method_params.rb +12 -7
- data/lib/steep/type_inference/send_args.rb +41 -35
- data/lib/steep/type_inference/type_env_builder.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +71 -2
- data/rbs_collection.steep.lock.yaml +18 -30
- data/rbs_collection.steep.yaml +1 -0
- data/sig/shims/language-server_protocol.rbs +20 -0
- data/sig/shims/tagged_logging.rbs +6 -0
- data/sig/steep/ast/annotation/collection.rbs +6 -6
- data/sig/steep/ast/types/class.rbs +3 -0
- data/sig/steep/ast/types/factory.rbs +38 -32
- data/sig/steep/ast/types/instance.rbs +3 -0
- data/sig/steep/ast/types/intersection.rbs +1 -1
- data/sig/steep/ast/types/literal.rbs +7 -7
- data/sig/steep/ast/types/name.rbs +14 -13
- data/sig/steep/ast/types/proc.rbs +3 -1
- data/sig/steep/ast/types/self.rbs +3 -0
- data/sig/steep/ast/types/var.rbs +1 -1
- data/sig/steep/diagnostic/ruby.rbs +30 -34
- data/sig/steep/drivers/annotations.rbs +17 -0
- data/sig/steep/drivers/check.rbs +33 -0
- data/sig/steep/drivers/checkfile.rbs +26 -0
- data/sig/steep/drivers/diagnostic_printer.rbs +25 -0
- data/sig/steep/drivers/init.rbs +19 -0
- data/sig/steep/drivers/langserver.rbs +35 -0
- data/sig/steep/drivers/print_project.rbs +15 -0
- data/sig/steep/drivers/stats.rbs +37 -0
- data/sig/steep/drivers/utils/driver_helper.rbs +23 -0
- data/sig/steep/drivers/utils/jobs_count.rbs +11 -0
- data/sig/steep/drivers/validate.rbs +15 -0
- data/sig/steep/drivers/vendor.rbs +19 -0
- data/sig/steep/drivers/watch.rbs +27 -0
- data/sig/steep/drivers/worker.rbs +31 -0
- data/sig/steep/equatable.rbs +11 -0
- data/sig/steep/index/rbs_index.rbs +91 -0
- data/sig/steep/index/signature_symbol_provider.rbs +29 -0
- data/sig/steep/index/source_index.rbs +63 -0
- data/sig/steep/interface/block.rbs +3 -1
- data/sig/steep/interface/builder.rbs +152 -0
- data/sig/steep/interface/function.rbs +67 -55
- data/sig/steep/interface/method_type.rbs +60 -12
- data/sig/steep/interface/shape.rbs +61 -0
- data/sig/steep/interface/substitution.rbs +18 -22
- data/sig/steep/interface/type_param.rbs +9 -1
- data/sig/steep/path_helper.rbs +7 -0
- data/sig/steep/project/pattern.rbs +10 -10
- data/sig/steep/project/target.rbs +2 -2
- data/sig/steep/project.rbs +15 -8
- data/sig/steep/server/base_worker.rbs +49 -0
- data/sig/steep/server/change_buffer.rbs +32 -0
- data/sig/steep/server/interaction_worker.rbs +41 -0
- data/sig/steep/server/lsp_formatter.rbs +29 -0
- data/sig/steep/server/master.rbs +260 -0
- data/sig/steep/server/type_check_worker.rbs +135 -0
- data/sig/steep/server/worker_process.rbs +29 -0
- data/sig/steep/services/completion_provider.rbs +5 -5
- data/sig/steep/services/content_change.rbs +14 -12
- data/sig/steep/services/file_loader.rbs +12 -4
- data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
- data/sig/steep/services/path_assignment.rbs +7 -7
- data/sig/steep/services/signature_service.rbs +67 -40
- data/sig/steep/services/type_check_service.rbs +53 -39
- data/sig/steep/subtyping/check.rbs +80 -44
- data/sig/steep/subtyping/relation.rbs +24 -22
- data/sig/steep/subtyping/result.rbs +48 -30
- data/sig/steep/subtyping/variable_variance.rbs +2 -0
- data/sig/steep/type_construction.rbs +132 -23
- data/sig/steep/type_inference/block_params.rbs +120 -18
- data/sig/steep/type_inference/context.rbs +45 -20
- data/sig/steep/type_inference/context_array.rbs +37 -0
- data/sig/steep/type_inference/logic_type_interpreter.rbs +3 -1
- data/sig/steep/type_inference/method_params.rbs +13 -9
- data/sig/steep/type_inference/send_args.rbs +229 -0
- data/sig/steep/type_inference/type_env_builder.rbs +1 -1
- data/sig/steep/typing.rbs +4 -4
- data/sig/steep.rbs +4 -2
- data/smoke/block/e.rb +12 -0
- data/smoke/block/e.rbs +4 -0
- data/smoke/block/test_expectations.yml +12 -0
- data/smoke/regression/block_param_split.rb +7 -0
- data/smoke/regression/block_param_split.rbs +3 -0
- data/smoke/regression/empty_yield.rb +5 -0
- data/smoke/regression/empty_yield.rbs +3 -0
- data/smoke/regression/test_expectations.yml +12 -0
- data/smoke/yield/test_expectations.yml +4 -4
- data/steep.gemspec +2 -1
- metadata +61 -9
- data/lib/steep/interface/interface.rb +0 -34
- data/sig/steep/interface/interface.rbs +0 -23
- 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,
|
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:
|
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::
|
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,
|
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
|
1602
|
-
if method_context.block_type
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
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,
|
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 =
|
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:
|
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
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
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
|
-
|
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 =
|
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
|
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
|
-
|
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
|
-
|
2950
|
-
|
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
|
-
|
2974
|
-
if
|
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
|
-
|
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
|
3068
|
-
|
3069
|
-
|
3070
|
-
|
3071
|
-
|
3072
|
-
|
3073
|
-
|
3074
|
-
|
3075
|
-
|
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
|
-
|
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
|
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,
|
3313
|
-
|
3314
|
-
|
3315
|
-
|
3316
|
-
|
3317
|
-
|
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 =
|
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
|
-
|
3424
|
-
|
3425
|
-
|
3426
|
-
|
3427
|
-
|
3428
|
-
|
3429
|
-
|
3430
|
-
|
3431
|
-
|
3432
|
-
|
3433
|
-
|
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,
|
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
|
3726
|
+
def type_block_without_hint(node:, block_annotations:, block_params:, block_body:)
|
3673
3727
|
unless block_params
|
3674
|
-
|
3675
|
-
|
3676
|
-
|
3677
|
-
|
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
|
-
|
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
|
-
|
3704
|
-
|
3705
|
-
|
3706
|
-
|
3707
|
-
|
3708
|
-
|
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
|
3716
|
-
|
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
|
-
|
3722
|
-
|
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
|
-
|
3727
|
-
|
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
|
-
|
3950
|
-
|
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
|
3961
|
-
checker.factory.deep_expand_alias(type
|
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(
|
4034
|
-
|
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
|
-
|
4044
|
-
|
4045
|
-
|
4046
|
-
|
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(
|
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
|
4057
|
-
|
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
|
-
|
4061
|
-
|
4062
|
-
|
4063
|
-
|
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
|
-
|
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
|