steep 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/ruby.yml +3 -2
- data/.gitignore +0 -1
- data/CHANGELOG.md +30 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +77 -0
- data/bin/output_test.rb +8 -2
- data/lib/steep.rb +4 -1
- data/lib/steep/ast/builtin.rb +7 -1
- data/lib/steep/ast/types/factory.rb +19 -25
- data/lib/steep/diagnostic/ruby.rb +137 -60
- data/lib/steep/diagnostic/signature.rb +34 -0
- data/lib/steep/equatable.rb +21 -0
- data/lib/steep/index/source_index.rb +55 -5
- data/lib/steep/interface/block.rb +4 -0
- data/lib/steep/interface/function.rb +798 -579
- data/lib/steep/server/interaction_worker.rb +239 -20
- data/lib/steep/server/master.rb +40 -19
- data/lib/steep/server/type_check_worker.rb +68 -0
- data/lib/steep/services/file_loader.rb +26 -19
- data/lib/steep/services/goto_service.rb +322 -0
- data/lib/steep/services/hover_content.rb +131 -79
- data/lib/steep/services/type_check_service.rb +25 -0
- data/lib/steep/source.rb +7 -10
- data/lib/steep/type_construction.rb +496 -518
- data/lib/steep/type_inference/block_params.rb +2 -5
- data/lib/steep/type_inference/method_params.rb +483 -0
- data/lib/steep/type_inference/send_args.rb +610 -128
- data/lib/steep/typing.rb +46 -21
- data/lib/steep/version.rb +1 -1
- data/sig/steep/type_inference/send_args.rbs +42 -0
- data/smoke/array/test_expectations.yml +3 -3
- data/smoke/block/c.rb +0 -1
- data/smoke/class/test_expectations.yml +12 -15
- data/smoke/const/test_expectations.yml +0 -10
- data/smoke/diagnostics-rbs/mixin-class-error.rbs +6 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
- data/smoke/diagnostics-ruby-unsat/Steepfile +5 -0
- data/smoke/diagnostics-ruby-unsat/a.rbs +3 -0
- data/smoke/diagnostics-ruby-unsat/test_expectations.yml +27 -0
- data/smoke/{diagnostics → diagnostics-ruby-unsat}/unsatisfiable_constraint.rb +0 -1
- data/smoke/diagnostics/a.rbs +0 -4
- data/smoke/diagnostics/different_method_parameter_kind.rb +9 -0
- data/smoke/diagnostics/method_arity_mismatch.rb +2 -2
- data/smoke/diagnostics/method_parameter_mismatch.rb +10 -0
- data/smoke/diagnostics/test_expectations.yml +108 -57
- data/smoke/ensure/test_expectations.yml +3 -3
- data/smoke/enumerator/test_expectations.yml +1 -1
- data/smoke/literal/test_expectations.yml +2 -2
- data/smoke/method/test_expectations.yml +11 -10
- data/smoke/regression/issue_372.rb +8 -0
- data/smoke/regression/issue_372.rbs +4 -0
- data/smoke/regression/test_expectations.yml +0 -12
- data/smoke/rescue/test_expectations.yml +3 -3
- data/smoke/toplevel/test_expectations.yml +3 -3
- data/smoke/tsort/test_expectations.yml +2 -2
- data/steep.gemspec +2 -2
- metadata +24 -10
@@ -383,6 +383,31 @@ module Steep
|
|
383
383
|
|
384
384
|
typing
|
385
385
|
end
|
386
|
+
|
387
|
+
def source_file?(path)
|
388
|
+
if source_files.key?(path)
|
389
|
+
project.target_for_source_path(path)
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
def signature_file?(path)
|
394
|
+
relative_path = project.relative_path(path)
|
395
|
+
targets = signature_services.select {|_, sig| sig.files.key?(relative_path) || sig.env_rbs_paths.include?(path) }
|
396
|
+
unless targets.empty?
|
397
|
+
targets.keys
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
def app_signature_file?(path)
|
402
|
+
target_names = signature_services.select {|_, sig| sig.files.key?(path) }.keys
|
403
|
+
unless target_names.empty?
|
404
|
+
target_names
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def lib_signature_file?(path)
|
409
|
+
signature_services.each_value.any? {|sig| sig.env_rbs_paths.include?(path) }
|
410
|
+
end
|
386
411
|
end
|
387
412
|
end
|
388
413
|
end
|
data/lib/steep/source.rb
CHANGED
@@ -35,28 +35,25 @@ module Steep
|
|
35
35
|
|
36
36
|
self.emit_lambda = true
|
37
37
|
self.emit_procarg0 = true
|
38
|
+
self.emit_kwargs = true
|
38
39
|
end
|
39
40
|
|
40
|
-
def self.
|
41
|
-
::Parser::
|
41
|
+
def self.new_parser
|
42
|
+
::Parser::Ruby30.new(Builder.new).tap do |parser|
|
42
43
|
parser.diagnostics.all_errors_are_fatal = true
|
43
44
|
parser.diagnostics.ignore_warnings = true
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
48
|
def self.parse(source_code, path:, factory:)
|
48
|
-
buffer = ::Parser::Source::Buffer.new(path.to_s, 1)
|
49
|
-
|
50
|
-
node = parser.parse(buffer)
|
49
|
+
buffer = ::Parser::Source::Buffer.new(path.to_s, 1, source: source_code)
|
50
|
+
node = new_parser().parse(buffer)
|
51
51
|
|
52
52
|
annotations = []
|
53
53
|
|
54
54
|
_, comments, _ = yield_self do
|
55
|
-
buffer = ::Parser::Source::Buffer.new(path.to_s)
|
56
|
-
buffer
|
57
|
-
parser = ::Parser::Ruby27.new
|
58
|
-
|
59
|
-
parser.tokenize(buffer)
|
55
|
+
buffer = ::Parser::Source::Buffer.new(path.to_s, 1, source: source_code)
|
56
|
+
new_parser().tokenize(buffer)
|
60
57
|
end
|
61
58
|
|
62
59
|
buffer = RBS::Buffer.new(name: path, content: source_code)
|
@@ -10,10 +10,7 @@ module Steep
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def with(type: self.type, constr: self.constr)
|
13
|
-
self.class.new(
|
14
|
-
type: type,
|
15
|
-
constr: constr
|
16
|
-
)
|
13
|
+
self.class.new(type: type, constr: constr)
|
17
14
|
end
|
18
15
|
|
19
16
|
def +(other)
|
@@ -162,23 +159,6 @@ module Steep
|
|
162
159
|
|
163
160
|
# constructor_method = method&.attributes&.include?(:constructor)
|
164
161
|
|
165
|
-
if method_type
|
166
|
-
var_types = TypeConstruction.parameter_types(args, method_type.type)
|
167
|
-
unless TypeConstruction.valid_parameter_env?(var_types, args.reject {|arg| arg.type == :blockarg}, method_type.type.params)
|
168
|
-
typing.add_error Diagnostic::Ruby::MethodArityMismatch.new(node: node, method_type: method_type)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
if (block_arg = args.find {|arg| arg.type == :blockarg})
|
173
|
-
if method_type&.block
|
174
|
-
block_type = AST::Types::Proc.new(type: method_type.block.type, block: nil)
|
175
|
-
if method_type.block.optional?
|
176
|
-
block_type = AST::Types::Union.build(types: [block_type, AST::Builtin.nil_type])
|
177
|
-
end
|
178
|
-
var_types[block_arg.children[0]] = block_type
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
162
|
super_method = if definition
|
183
163
|
if (this_method = definition.methods[method_name])
|
184
164
|
if module_context&.class_name == this_method.defined_in
|
@@ -219,13 +199,21 @@ module Steep
|
|
219
199
|
class_type: module_context.module_type
|
220
200
|
)
|
221
201
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
202
|
+
method_params =
|
203
|
+
if method_type
|
204
|
+
TypeInference::MethodParams.build(node: node, method_type: method_type)
|
205
|
+
else
|
206
|
+
TypeInference::MethodParams.empty(node: node)
|
207
|
+
end
|
208
|
+
|
209
|
+
method_params.each_param do |param|
|
210
|
+
lvar_env = lvar_env.assign(param.name, type: param.var_type, node: param.node) {
|
211
|
+
raise "Unexpected assignment error: #{param.name}"
|
212
|
+
}
|
213
|
+
end
|
214
|
+
|
215
|
+
method_params.errors.each do |error|
|
216
|
+
typing.add_error error
|
229
217
|
end
|
230
218
|
|
231
219
|
lvar_env = lvar_env.annotate(annots)
|
@@ -692,7 +680,7 @@ module Steep
|
|
692
680
|
end
|
693
681
|
|
694
682
|
def synthesize(node, hint: nil, condition: false)
|
695
|
-
Steep.logger.tagged "synthesize:(#{node.location.expression.to_s.split(/:/, 2).last})" do
|
683
|
+
Steep.logger.tagged "synthesize:(#{node.location&.yield_self {|loc| loc.expression.to_s.split(/:/, 2).last } || "-"})" do
|
696
684
|
Steep.logger.debug node.type
|
697
685
|
case node.type
|
698
686
|
when :begin, :kwbegin
|
@@ -732,8 +720,17 @@ module Steep
|
|
732
720
|
when :__skip__
|
733
721
|
add_typing(node, type: AST::Builtin.any_type)
|
734
722
|
else
|
735
|
-
if
|
736
|
-
hint
|
723
|
+
if declared_type = context.lvar_env.declared_types[name]&.type
|
724
|
+
case hint
|
725
|
+
when nil
|
726
|
+
hint = declared_type
|
727
|
+
else
|
728
|
+
if check_relation(sub_type: declared_type, super_type: hint).success?
|
729
|
+
# declared_type is compatible with hint and more specific to hint.
|
730
|
+
# This typically happens when hint is untyped, top, or void.
|
731
|
+
hint = declared_type
|
732
|
+
end
|
733
|
+
end
|
737
734
|
end
|
738
735
|
|
739
736
|
rhs_result = synthesize(rhs, hint: hint)
|
@@ -751,7 +748,7 @@ module Steep
|
|
751
748
|
end
|
752
749
|
end
|
753
750
|
|
754
|
-
add_typing(node, type: rhs_result.type
|
751
|
+
constr.add_typing(node, type: rhs_result.type)
|
755
752
|
end
|
756
753
|
end
|
757
754
|
|
@@ -888,13 +885,12 @@ module Steep
|
|
888
885
|
checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[decl])
|
889
886
|
}
|
890
887
|
)
|
891
|
-
args = TypeInference::SendArgs.from_nodes(node.children.dup)
|
892
888
|
|
893
889
|
call, constr = type_method_call(node,
|
894
890
|
receiver_type: self_type,
|
895
891
|
method_name: method_context.name,
|
896
892
|
method: super_method,
|
897
|
-
|
893
|
+
arguments: node.children,
|
898
894
|
block_params: nil,
|
899
895
|
block_body: nil,
|
900
896
|
topdown_hint: true)
|
@@ -940,18 +936,46 @@ module Steep
|
|
940
936
|
end
|
941
937
|
end
|
942
938
|
|
939
|
+
when :numblock
|
940
|
+
yield_self do
|
941
|
+
send_node, max_num, body = node.children
|
942
|
+
|
943
|
+
if max_num == 1
|
944
|
+
arg_nodes = [Parser::AST::Node.new(:procarg0, [:_1])]
|
945
|
+
else
|
946
|
+
arg_nodes = max_num.times.map {|i| Parser::AST::Node.new(:arg, [:"_#{i+1}"]) }
|
947
|
+
end
|
948
|
+
|
949
|
+
params = Parser::AST::Node.new(:args, arg_nodes)
|
950
|
+
|
951
|
+
if send_node.type == :lambda
|
952
|
+
type_lambda(node, block_params: params, block_body: body, type_hint: hint)
|
953
|
+
else
|
954
|
+
type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend)
|
955
|
+
end
|
956
|
+
end
|
957
|
+
|
943
958
|
when :def
|
944
959
|
yield_self do
|
945
960
|
name, args_node, body_node = node.children
|
946
961
|
|
947
|
-
new = for_new_method(
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
962
|
+
new = for_new_method(
|
963
|
+
name,
|
964
|
+
node,
|
965
|
+
args: args_node.children,
|
966
|
+
self_type: module_context&.instance_type,
|
967
|
+
definition: module_context&.instance_definition
|
968
|
+
)
|
952
969
|
new.typing.add_context_for_node(node, context: new.context)
|
953
970
|
new.typing.add_context_for_body(node, context: new.context)
|
954
971
|
|
972
|
+
new.method_context.tap do |method_context|
|
973
|
+
if method_context.method
|
974
|
+
method_name = InstanceMethodName.new(type_name: method_context.method.implemented_in, method_name: name)
|
975
|
+
new.typing.source_index.add_definition(method: method_name, definition: node)
|
976
|
+
end
|
977
|
+
end
|
978
|
+
|
955
979
|
new = new.synthesize_children(args_node)
|
956
980
|
|
957
981
|
body_pair = if body_node
|
@@ -990,10 +1014,13 @@ module Steep
|
|
990
1014
|
end
|
991
1015
|
|
992
1016
|
if body_node
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
1017
|
+
# Add context to ranges from the end of the method body to the beginning of the `end` keyword
|
1018
|
+
if node.loc.end
|
1019
|
+
# Skip end-less def
|
1020
|
+
begin_pos = body_node.loc.expression.end_pos
|
1021
|
+
end_pos = node.loc.end.begin_pos
|
1022
|
+
typing.add_context(begin_pos..end_pos, context: body_pair.context)
|
1023
|
+
end
|
997
1024
|
end
|
998
1025
|
|
999
1026
|
if module_context
|
@@ -1006,24 +1033,43 @@ module Steep
|
|
1006
1033
|
when :defs
|
1007
1034
|
synthesize(node.children[0]).type.tap do |self_type|
|
1008
1035
|
self_type = expand_self(self_type)
|
1009
|
-
definition =
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1036
|
+
definition =
|
1037
|
+
case self_type
|
1038
|
+
when AST::Types::Name::Instance
|
1039
|
+
name = self_type.name
|
1040
|
+
checker.factory.definition_builder.build_instance(name)
|
1041
|
+
when AST::Types::Name::Singleton
|
1042
|
+
name = self_type.name
|
1043
|
+
checker.factory.definition_builder.build_singleton(name)
|
1044
|
+
end
|
1017
1045
|
|
1018
1046
|
args_node = node.children[2]
|
1019
|
-
new = for_new_method(
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1047
|
+
new = for_new_method(
|
1048
|
+
node.children[1],
|
1049
|
+
node,
|
1050
|
+
args: args_node.children,
|
1051
|
+
self_type: self_type,
|
1052
|
+
definition: definition
|
1053
|
+
)
|
1024
1054
|
new.typing.add_context_for_node(node, context: new.context)
|
1025
1055
|
new.typing.add_context_for_body(node, context: new.context)
|
1026
1056
|
|
1057
|
+
new.method_context.tap do |method_context|
|
1058
|
+
if method_context.method
|
1059
|
+
name_ = node.children[1]
|
1060
|
+
|
1061
|
+
method_name =
|
1062
|
+
case self_type
|
1063
|
+
when AST::Types::Name::Instance
|
1064
|
+
InstanceMethodName.new(type_name: method_context.method.implemented_in, method_name: name_)
|
1065
|
+
when AST::Types::Name::Singleton
|
1066
|
+
SingletonMethodName.new(type_name: method_context.method.implemented_in, method_name: name_)
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
new.typing.source_index.add_definition(method: method_name, definition: node)
|
1070
|
+
end
|
1071
|
+
end
|
1072
|
+
|
1027
1073
|
new = new.synthesize_children(args_node)
|
1028
1074
|
|
1029
1075
|
each_child_node(node.children[2]) do |arg|
|
@@ -1115,15 +1161,16 @@ module Steep
|
|
1115
1161
|
)
|
1116
1162
|
end
|
1117
1163
|
else
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1164
|
+
unless break_type.is_a?(AST::Types::Bot)
|
1165
|
+
check_relation(sub_type: AST::Builtin.nil_type, super_type: break_type).else do |result|
|
1166
|
+
typing.add_error(
|
1167
|
+
Diagnostic::Ruby::ImplicitBreakValueMismatch.new(
|
1168
|
+
node: node,
|
1169
|
+
jump_type: break_type,
|
1170
|
+
result: result
|
1171
|
+
)
|
1125
1172
|
)
|
1126
|
-
|
1173
|
+
end
|
1127
1174
|
end
|
1128
1175
|
end
|
1129
1176
|
else
|
@@ -1335,52 +1382,20 @@ module Steep
|
|
1335
1382
|
add_typing(node, type: AST::Types::Boolean.new)
|
1336
1383
|
end
|
1337
1384
|
|
1338
|
-
when :hash
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
if AST::Builtin::Hash.instance_type
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
value_types = []
|
1349
|
-
|
1350
|
-
each_child_node(node) do |child|
|
1351
|
-
case child.type
|
1352
|
-
when :pair
|
1353
|
-
key, value = child.children
|
1354
|
-
key_types << synthesize(key, hint: key_hint).type.yield_self do |type|
|
1355
|
-
select_super_type(type, key_hint)
|
1356
|
-
end
|
1357
|
-
value_types << synthesize(value, hint: value_hint).type.yield_self do |type|
|
1358
|
-
select_super_type(type, value_hint)
|
1359
|
-
end
|
1360
|
-
when :kwsplat
|
1361
|
-
expand_alias(synthesize(child.children[0]).type) do |splat_type, original_type|
|
1362
|
-
if AST::Builtin::Hash.instance_type?(splat_type)
|
1363
|
-
key_types << splat_type.args[0]
|
1364
|
-
value_types << splat_type.args[1]
|
1365
|
-
else
|
1366
|
-
typing.add_error Diagnostic::Ruby::UnexpectedSplat.new(node: child, type: original_type)
|
1367
|
-
key_types << AST::Builtin.any_type
|
1368
|
-
value_types << AST::Builtin.any_type
|
1369
|
-
end
|
1370
|
-
end
|
1385
|
+
when :hash, :kwargs
|
1386
|
+
# :kwargs happens for method calls with keyword argument, but the method doesn't have keyword params.
|
1387
|
+
# Conversion from kwargs to hash happens, and this when-clause is to support it.
|
1388
|
+
type_hash(node, hint: hint).tap do |pair|
|
1389
|
+
if pair.type == AST::Builtin::Hash.instance_type(fill_untyped: true)
|
1390
|
+
case hint
|
1391
|
+
when AST::Types::Any, AST::Types::Top, AST::Types::Void
|
1392
|
+
# ok
|
1393
|
+
when hint == pair.type
|
1394
|
+
# ok
|
1371
1395
|
else
|
1372
|
-
|
1396
|
+
pair.constr.typing.add_error Diagnostic::Ruby::FallbackAny.new(node: node)
|
1373
1397
|
end
|
1374
1398
|
end
|
1375
|
-
|
1376
|
-
key_type = key_types.empty? ? AST::Builtin.any_type : AST::Types::Union.build(types: key_types)
|
1377
|
-
value_type = value_types.empty? ? AST::Builtin.any_type : AST::Types::Union.build(types: value_types)
|
1378
|
-
|
1379
|
-
if key_types.empty? && value_types.empty? && !hint
|
1380
|
-
typing.add_error Diagnostic::Ruby::FallbackAny.new(node: node)
|
1381
|
-
end
|
1382
|
-
|
1383
|
-
add_typing(node, type: AST::Builtin::Hash.instance_type(key_type, value_type))
|
1384
1399
|
end
|
1385
1400
|
|
1386
1401
|
when :dstr, :xstr
|
@@ -1443,9 +1458,22 @@ module Steep
|
|
1443
1458
|
constr = self
|
1444
1459
|
|
1445
1460
|
name, _ = node.children
|
1446
|
-
|
1461
|
+
if name.type == :const
|
1462
|
+
# skip the last constant reference
|
1463
|
+
if const_parent = name.children[0]
|
1464
|
+
_, constr = constr.synthesize(const_parent)
|
1465
|
+
end
|
1466
|
+
else
|
1467
|
+
_, constr = constr.synthesize(name)
|
1468
|
+
end
|
1447
1469
|
|
1448
1470
|
for_module(node).yield_self do |constructor|
|
1471
|
+
if module_type = constructor.module_context&.module_type
|
1472
|
+
_, constructor = constructor.add_typing(name, type: module_type)
|
1473
|
+
else
|
1474
|
+
_, constructor = constructor.fallback_to_any(name)
|
1475
|
+
end
|
1476
|
+
|
1449
1477
|
constructor.typing.source_index.add_definition(
|
1450
1478
|
constant: constructor.module_context.class_name,
|
1451
1479
|
definition: node
|
@@ -1642,8 +1670,7 @@ module Steep
|
|
1642
1670
|
tuples.each do |tuple|
|
1643
1671
|
typing.new_child(node_range) do |child_typing|
|
1644
1672
|
if pair = with_new_typing(child_typing).try_tuple_type(node, tuple)
|
1645
|
-
|
1646
|
-
return pair.with(constr: pair.constr.with_new_typing(typing))
|
1673
|
+
return pair.with(constr: pair.constr.save_typing)
|
1647
1674
|
end
|
1648
1675
|
end
|
1649
1676
|
end
|
@@ -1654,8 +1681,7 @@ module Steep
|
|
1654
1681
|
typing.new_child(node_range) do |child_typing|
|
1655
1682
|
pair = with_new_typing(child_typing).try_array_type(node, array)
|
1656
1683
|
if pair.constr.check_relation(sub_type: pair.type, super_type: hint).success?
|
1657
|
-
|
1658
|
-
return pair.with(constr: pair.constr.with_new_typing(typing))
|
1684
|
+
return pair.with(constr: pair.constr.save_typing)
|
1659
1685
|
end
|
1660
1686
|
end
|
1661
1687
|
end
|
@@ -2250,7 +2276,9 @@ module Steep
|
|
2250
2276
|
unless return_types.empty?
|
2251
2277
|
type = AST::Types::Proc.new(
|
2252
2278
|
type: Interface::Function.new(
|
2253
|
-
params: Interface::Function::Params.empty.
|
2279
|
+
params: Interface::Function::Params.empty.with_first_param(
|
2280
|
+
Interface::Function::Params::PositionalParams::Required.new(param_type)
|
2281
|
+
),
|
2254
2282
|
return_type: AST::Types::Union.build(types: return_types),
|
2255
2283
|
location: nil
|
2256
2284
|
),
|
@@ -2348,6 +2376,7 @@ module Steep
|
|
2348
2376
|
|
2349
2377
|
else
|
2350
2378
|
typing.add_error(Diagnostic::Ruby::UnsupportedSyntax.new(node: node))
|
2379
|
+
add_typing(node, type: AST::Builtin.any_type)
|
2351
2380
|
|
2352
2381
|
end.tap do |pair|
|
2353
2382
|
unless pair.is_a?(Pair) && !pair.type.is_a?(Pair)
|
@@ -2697,11 +2726,10 @@ module Steep
|
|
2697
2726
|
method = interface.methods[method_name]
|
2698
2727
|
|
2699
2728
|
if method
|
2700
|
-
args = TypeInference::SendArgs.from_nodes(arguments)
|
2701
2729
|
call, constr = type_method_call(node,
|
2702
2730
|
method: method,
|
2703
2731
|
method_name: method_name,
|
2704
|
-
|
2732
|
+
arguments: arguments,
|
2705
2733
|
block_params: block_params,
|
2706
2734
|
block_body: block_body,
|
2707
2735
|
receiver_type: receiver_type,
|
@@ -2881,27 +2909,22 @@ module Steep
|
|
2881
2909
|
end
|
2882
2910
|
end
|
2883
2911
|
|
2884
|
-
def type_method_call(node, method_name:, receiver_type:, method:,
|
2912
|
+
def type_method_call(node, method_name:, receiver_type:, method:, arguments:, block_params:, block_body:, topdown_hint:)
|
2885
2913
|
node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
|
2886
2914
|
|
2887
|
-
results = method.method_types.
|
2915
|
+
results = method.method_types.map do |method_type|
|
2888
2916
|
Steep.logger.tagged method_type.to_s do
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
block_params: block_params,
|
2901
|
-
block_body: block_body,
|
2902
|
-
topdown_hint: topdown_hint
|
2903
|
-
)
|
2904
|
-
end
|
2917
|
+
typing.new_child(node_range) do |child_typing|
|
2918
|
+
self.with_new_typing(child_typing).try_method_type(
|
2919
|
+
node,
|
2920
|
+
receiver_type: receiver_type,
|
2921
|
+
method_name: method_name,
|
2922
|
+
method_type: method_type,
|
2923
|
+
arguments: arguments,
|
2924
|
+
block_params: block_params,
|
2925
|
+
block_body: block_body,
|
2926
|
+
topdown_hint: topdown_hint
|
2927
|
+
)
|
2905
2928
|
end
|
2906
2929
|
end
|
2907
2930
|
end
|
@@ -2941,138 +2964,34 @@ module Steep
|
|
2941
2964
|
]
|
2942
2965
|
end
|
2943
2966
|
|
2944
|
-
def
|
2945
|
-
|
2946
|
-
|
2947
|
-
case node.type
|
2948
|
-
when :hash
|
2949
|
-
keyword_hash_type = AST::Builtin::Hash.instance_type(AST::Builtin::Symbol.instance_type,
|
2950
|
-
AST::Builtin.any_type)
|
2951
|
-
add_typing node, type: keyword_hash_type
|
2952
|
-
|
2953
|
-
given_keys = Set.new()
|
2954
|
-
|
2955
|
-
node.children.each do |element|
|
2956
|
-
case element.type
|
2957
|
-
when :pair
|
2958
|
-
key_node, value_node = element.children
|
2959
|
-
|
2960
|
-
case key_node.type
|
2961
|
-
when :sym
|
2962
|
-
key_symbol = key_node.children[0]
|
2963
|
-
keyword_type = case
|
2964
|
-
when params.required_keywords.key?(key_symbol)
|
2965
|
-
params.required_keywords[key_symbol]
|
2966
|
-
when params.optional_keywords.key?(key_symbol)
|
2967
|
-
AST::Types::Union.build(
|
2968
|
-
types: [params.optional_keywords[key_symbol],
|
2969
|
-
AST::Builtin.nil_type]
|
2970
|
-
)
|
2971
|
-
when params.rest_keywords
|
2972
|
-
params.rest_keywords
|
2973
|
-
end
|
2974
|
-
|
2975
|
-
add_typing key_node, type: AST::Builtin::Symbol.instance_type
|
2976
|
-
|
2977
|
-
given_keys << key_symbol
|
2978
|
-
|
2979
|
-
if keyword_type
|
2980
|
-
check(value_node, keyword_type, constraints: constraints) do |expected, actual, result|
|
2981
|
-
return Diagnostic::Ruby::IncompatibleAssignment.new(
|
2982
|
-
node: value_node,
|
2983
|
-
lhs_type: expected,
|
2984
|
-
rhs_type: actual,
|
2985
|
-
result: result
|
2986
|
-
)
|
2987
|
-
end
|
2988
|
-
else
|
2989
|
-
synthesize(value_node)
|
2990
|
-
end
|
2991
|
-
|
2992
|
-
else
|
2993
|
-
check(key_node, AST::Builtin::Symbol.instance_type, constraints: constraints) do |expected, actual, result|
|
2994
|
-
return Diagnostic::Ruby::IncompatibleAssignment.new(
|
2995
|
-
node: key_node,
|
2996
|
-
lhs_type: expected,
|
2997
|
-
rhs_type: actual,
|
2998
|
-
result: result
|
2999
|
-
)
|
3000
|
-
end
|
3001
|
-
end
|
3002
|
-
|
3003
|
-
when :kwsplat
|
3004
|
-
Steep.logger.warn("Keyword arg with kwsplat(**) node are not supported.")
|
3005
|
-
|
3006
|
-
check(element.children[0], keyword_hash_type, constraints: constraints) do |expected, actual, result|
|
3007
|
-
return Diagnostic::Ruby::IncompatibleAssignment.new(
|
3008
|
-
node: node,
|
3009
|
-
lhs_type: expected,
|
3010
|
-
rhs_type: actual,
|
3011
|
-
result: result
|
3012
|
-
)
|
3013
|
-
end
|
3014
|
-
|
3015
|
-
given_keys = true
|
3016
|
-
end
|
3017
|
-
end
|
2967
|
+
def inspect
|
2968
|
+
"#<#{self.class}>"
|
2969
|
+
end
|
3018
2970
|
|
3019
|
-
|
3020
|
-
|
3021
|
-
missing_keywords = Set.new(params.required_keywords.keys) - given_keys
|
3022
|
-
unless missing_keywords.empty?
|
3023
|
-
return Diagnostic::Ruby::MissingKeyword.new(
|
3024
|
-
node: node,
|
3025
|
-
missing_keywords: missing_keywords
|
3026
|
-
)
|
3027
|
-
end
|
2971
|
+
def with_child_typing(range:)
|
2972
|
+
constr = with_new_typing(typing.new_child(range: range))
|
3028
2973
|
|
3029
|
-
|
3030
|
-
|
3031
|
-
return Diagnostic::Ruby::UnexpectedKeyword.new(
|
3032
|
-
node: node,
|
3033
|
-
unexpected_keywords: extra_keywords
|
3034
|
-
)
|
3035
|
-
end
|
3036
|
-
end
|
2974
|
+
if block_given?
|
2975
|
+
yield constr
|
3037
2976
|
else
|
3038
|
-
|
3039
|
-
|
3040
|
-
|
3041
|
-
value_types = params.required_keywords.values +
|
3042
|
-
params.optional_keywords.values.map {|type| AST::Types::Union.build(types: [type, AST::Builtin.nil_type])} +
|
3043
|
-
[params.rest_keywords]
|
3044
|
-
|
3045
|
-
hash_type = AST::Builtin::Hash.instance_type(
|
3046
|
-
AST::Builtin::Symbol.instance_type,
|
3047
|
-
AST::Types::Union.build(types: value_types)
|
3048
|
-
)
|
3049
|
-
else
|
3050
|
-
hash_elements = params.required_keywords.merge(
|
3051
|
-
params.optional_keywords.transform_values do |type|
|
3052
|
-
AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
|
3053
|
-
end
|
3054
|
-
)
|
3055
|
-
|
3056
|
-
hash_type = AST::Types::Record.new(elements: hash_elements)
|
3057
|
-
end
|
2977
|
+
constr
|
2978
|
+
end
|
2979
|
+
end
|
3058
2980
|
|
3059
|
-
|
2981
|
+
# Bypass :splat and :kwsplat
|
2982
|
+
def bypass_splat(node)
|
2983
|
+
splat = node.type == :splat || node.type == :kwsplat
|
3060
2984
|
|
3061
|
-
|
3062
|
-
|
3063
|
-
|
3064
|
-
|
3065
|
-
|
3066
|
-
|
3067
|
-
result: result
|
3068
|
-
)
|
3069
|
-
end
|
2985
|
+
if splat
|
2986
|
+
pair = yield(node.children[0])
|
2987
|
+
pair.constr.add_typing(node, type: pair.type)
|
2988
|
+
pair
|
2989
|
+
else
|
2990
|
+
yield node
|
3070
2991
|
end
|
3071
|
-
|
3072
|
-
nil
|
3073
2992
|
end
|
3074
2993
|
|
3075
|
-
def try_method_type(node, receiver_type:, method_name:, method_type:,
|
2994
|
+
def try_method_type(node, receiver_type:, method_name:, method_type:, arguments:, block_params:, block_body:, topdown_hint:)
|
3076
2995
|
fresh_types = method_type.type_params.map {|x| AST::Types::Var.fresh(x)}
|
3077
2996
|
fresh_vars = Set.new(fresh_types.map(&:name))
|
3078
2997
|
instantiation = Interface::Substitution.build(method_type.type_params, fresh_types)
|
@@ -3087,38 +3006,90 @@ module Steep
|
|
3087
3006
|
|
3088
3007
|
errors = []
|
3089
3008
|
|
3090
|
-
|
3091
|
-
|
3092
|
-
|
3093
|
-
|
3094
|
-
|
3009
|
+
args = TypeInference::SendArgs.new(node: node, arguments: arguments, method_name: method_name, method_type: method_type)
|
3010
|
+
es = args.each do |arg|
|
3011
|
+
case arg
|
3012
|
+
when TypeInference::SendArgs::PositionalArgs::NodeParamPair
|
3013
|
+
_, constr = constr.type_check_argument(
|
3014
|
+
arg.node,
|
3015
|
+
type: arg.param.type,
|
3016
|
+
receiver_type: receiver_type,
|
3017
|
+
constraints: constraints,
|
3018
|
+
errors: errors
|
3019
|
+
)
|
3095
3020
|
|
3096
|
-
|
3097
|
-
|
3098
|
-
|
3099
|
-
|
3100
|
-
|
3021
|
+
when TypeInference::SendArgs::PositionalArgs::NodeTypePair
|
3022
|
+
_, constr = bypass_splat(arg.node) do |n|
|
3023
|
+
constr.type_check_argument(
|
3024
|
+
n,
|
3025
|
+
type: arg.node_type,
|
3026
|
+
receiver_type: receiver_type,
|
3027
|
+
constraints: constraints,
|
3028
|
+
report_node: arg.node,
|
3029
|
+
errors: errors
|
3030
|
+
)
|
3031
|
+
end
|
3101
3032
|
|
3102
|
-
|
3103
|
-
|
3104
|
-
|
3105
|
-
|
3106
|
-
|
3107
|
-
|
3033
|
+
when TypeInference::SendArgs::PositionalArgs::UnexpectedArg
|
3034
|
+
_, constr = bypass_splat(arg.node) do |n|
|
3035
|
+
constr.synthesize(n)
|
3036
|
+
end
|
3037
|
+
|
3038
|
+
when TypeInference::SendArgs::PositionalArgs::SplatArg
|
3039
|
+
arg_type, _ = constr
|
3040
|
+
.with_child_typing(range: arg.node.loc.expression.begin_pos ... arg.node.loc.expression.end_pos)
|
3041
|
+
.try_tuple_type!(arg.node.children[0])
|
3042
|
+
arg.type = arg_type
|
3043
|
+
|
3044
|
+
when TypeInference::SendArgs::PositionalArgs::MissingArg
|
3045
|
+
# ignore
|
3046
|
+
|
3047
|
+
when TypeInference::SendArgs::KeywordArgs::ArgTypePairs
|
3048
|
+
arg.pairs.each do |node, type|
|
3049
|
+
_, constr = bypass_splat(node) do |node|
|
3050
|
+
constr.type_check_argument(
|
3051
|
+
node,
|
3052
|
+
type: type,
|
3053
|
+
receiver_type: receiver_type,
|
3054
|
+
constraints: constraints,
|
3055
|
+
errors: errors
|
3056
|
+
)
|
3057
|
+
end
|
3058
|
+
end
|
3059
|
+
|
3060
|
+
when TypeInference::SendArgs::KeywordArgs::UnexpectedKeyword
|
3061
|
+
if arg.node.type == :pair
|
3062
|
+
arg.node.children.each do |nn|
|
3063
|
+
_, constr = constr.synthesize(nn)
|
3064
|
+
end
|
3065
|
+
else
|
3066
|
+
_, constr = bypass_splat(arg.node) do |n|
|
3067
|
+
constr.synthesize(n)
|
3068
|
+
end
|
3108
3069
|
end
|
3109
|
-
else
|
3110
|
-
# keyword
|
3111
|
-
result = constr.check_keyword_arg(receiver_type: receiver_type,
|
3112
|
-
node: pair,
|
3113
|
-
method_type: method_type,
|
3114
|
-
constraints: constraints)
|
3115
3070
|
|
3116
|
-
|
3117
|
-
|
3071
|
+
when TypeInference::SendArgs::KeywordArgs::SplatArg
|
3072
|
+
type, _ = bypass_splat(arg.node) do |sp_node|
|
3073
|
+
if sp_node.type == :hash
|
3074
|
+
pair = constr.type_hash_record(sp_node, nil) and break pair
|
3075
|
+
end
|
3076
|
+
|
3077
|
+
constr.synthesize(sp_node)
|
3118
3078
|
end
|
3079
|
+
|
3080
|
+
arg.type = type
|
3081
|
+
|
3082
|
+
when TypeInference::SendArgs::KeywordArgs::MissingKeyword
|
3083
|
+
# ignore
|
3084
|
+
else
|
3085
|
+
raise arg.inspect
|
3119
3086
|
end
|
3087
|
+
|
3088
|
+
constr
|
3120
3089
|
end
|
3121
3090
|
|
3091
|
+
errors.push(*es)
|
3092
|
+
|
3122
3093
|
if block_params
|
3123
3094
|
# block is given
|
3124
3095
|
block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
@@ -3261,104 +3232,105 @@ module Steep
|
|
3261
3232
|
)
|
3262
3233
|
end
|
3263
3234
|
else
|
3264
|
-
|
3265
|
-
|
3266
|
-
|
3267
|
-
|
3268
|
-
|
3269
|
-
|
3235
|
+
arg = args.block_pass_arg
|
3236
|
+
|
3237
|
+
case
|
3238
|
+
when arg.compatible?
|
3239
|
+
if arg.node
|
3240
|
+
subst = constraints.solution(
|
3270
3241
|
checker,
|
3271
|
-
variance: variance,
|
3272
|
-
variables: fresh_vars,
|
3273
3242
|
self_type: self_type,
|
3274
3243
|
instance_type: module_context.instance_type,
|
3275
|
-
class_type: module_context.module_type
|
3244
|
+
class_type: module_context.module_type,
|
3245
|
+
variance: variance,
|
3246
|
+
variables: occurence.params
|
3276
3247
|
)
|
3277
|
-
|
3278
|
-
|
3279
|
-
|
3280
|
-
|
3248
|
+
|
3249
|
+
block_type = arg.node_type.subst(subst)
|
3250
|
+
|
3251
|
+
node_type, constr = constr.synthesize(arg.node, hint: block_type)
|
3252
|
+
nil_block =
|
3253
|
+
constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success? &&
|
3254
|
+
!node_type.is_a?(AST::Types::Any)
|
3255
|
+
|
3256
|
+
unless nil_block
|
3257
|
+
constr.check_relation(sub_type: node_type, super_type: block_type, constraints: constraints).else do |result|
|
3258
|
+
errors << Diagnostic::Ruby::BlockTypeMismatch.new(
|
3259
|
+
node: arg.node,
|
3260
|
+
expected: block_type,
|
3261
|
+
actual: node_type,
|
3262
|
+
result: result
|
3263
|
+
)
|
3264
|
+
end
|
3265
|
+
end
|
3266
|
+
|
3267
|
+
subst = constraints.solution(
|
3281
3268
|
checker,
|
3282
|
-
variance: variance,
|
3283
|
-
variables: fresh_vars,
|
3284
3269
|
self_type: self_type,
|
3285
3270
|
instance_type: module_context.instance_type,
|
3286
|
-
class_type: module_context.module_type
|
3271
|
+
class_type: module_context.module_type,
|
3272
|
+
variance: variance,
|
3273
|
+
variables: method_type.free_variables
|
3287
3274
|
)
|
3288
|
-
method_type = method_type.subst(s)
|
3289
3275
|
|
3290
|
-
|
3291
|
-
|
3292
|
-
|
3293
|
-
|
3276
|
+
method_type = method_type.subst(subst)
|
3277
|
+
|
3278
|
+
if nil_block && arg.block.required?
|
3279
|
+
# Passing no block
|
3280
|
+
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3294
3281
|
node: node,
|
3295
3282
|
method_type: method_type
|
3296
3283
|
)
|
3297
3284
|
end
|
3298
|
-
|
3299
|
-
|
3300
|
-
unless args.block_pass_arg
|
3301
|
-
# Required block is missing
|
3302
|
-
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3303
|
-
node: node,
|
3304
|
-
method_type: method_type
|
3305
|
-
)
|
3306
|
-
|
3307
|
-
s = constraints.solution(
|
3285
|
+
else
|
3286
|
+
subst = constraints.solution(
|
3308
3287
|
checker,
|
3309
|
-
variance: variance,
|
3310
|
-
variables: fresh_vars,
|
3311
3288
|
self_type: self_type,
|
3312
3289
|
instance_type: module_context.instance_type,
|
3313
|
-
class_type: module_context.module_type
|
3290
|
+
class_type: module_context.module_type,
|
3291
|
+
variance: variance,
|
3292
|
+
variables: method_type.free_variables
|
3314
3293
|
)
|
3315
|
-
method_type = method_type.subst(s)
|
3316
|
-
else
|
3317
|
-
begin
|
3318
|
-
method_type = method_type.subst(
|
3319
|
-
constraints.solution(
|
3320
|
-
checker,
|
3321
|
-
self_type: self_type,
|
3322
|
-
instance_type: module_context.instance_type,
|
3323
|
-
class_type: module_context.module_type,
|
3324
|
-
variance: variance,
|
3325
|
-
variables: occurence.params
|
3326
|
-
)
|
3327
|
-
)
|
3328
|
-
hint_type = if topdown_hint
|
3329
|
-
AST::Types::Proc.new(type: method_type.block.type, block: nil)
|
3330
|
-
end
|
3331
|
-
given_block_type, constr = constr.synthesize(args.block_pass_arg, hint: hint_type)
|
3332
|
-
method_block_type = method_type.block.yield_self {|expected_block|
|
3333
|
-
proc_type = AST::Types::Proc.new(type: expected_block.type, block: nil)
|
3334
|
-
if expected_block.optional?
|
3335
|
-
AST::Builtin.optional(proc_type)
|
3336
|
-
else
|
3337
|
-
proc_type
|
3338
|
-
end
|
3339
|
-
}
|
3340
3294
|
|
3341
|
-
|
3342
|
-
|
3343
|
-
errors << Diagnostic::Ruby::BlockTypeMismatch.new(
|
3344
|
-
node: args.block_pass_arg,
|
3345
|
-
expected: method_block_type,
|
3346
|
-
actual: given_block_type,
|
3347
|
-
result: result
|
3348
|
-
)
|
3349
|
-
end
|
3295
|
+
method_type = method_type.subst(subst)
|
3296
|
+
end
|
3350
3297
|
|
3351
|
-
|
3352
|
-
|
3353
|
-
|
3354
|
-
|
3355
|
-
|
3356
|
-
|
3357
|
-
|
3358
|
-
|
3359
|
-
|
3360
|
-
|
3361
|
-
|
3298
|
+
when arg.block_missing?
|
3299
|
+
subst = constraints.solution(
|
3300
|
+
checker,
|
3301
|
+
self_type: self_type,
|
3302
|
+
instance_type: module_context.instance_type,
|
3303
|
+
class_type: module_context.module_type,
|
3304
|
+
variance: variance,
|
3305
|
+
variables: method_type.free_variables
|
3306
|
+
)
|
3307
|
+
|
3308
|
+
method_type = method_type.subst(subst)
|
3309
|
+
|
3310
|
+
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3311
|
+
node: node,
|
3312
|
+
method_type: method_type
|
3313
|
+
)
|
3314
|
+
|
3315
|
+
when arg.unexpected_block?
|
3316
|
+
subst = constraints.solution(
|
3317
|
+
checker,
|
3318
|
+
self_type: self_type,
|
3319
|
+
instance_type: module_context.instance_type,
|
3320
|
+
class_type: module_context.module_type,
|
3321
|
+
variance: variance,
|
3322
|
+
variables: method_type.free_variables
|
3323
|
+
)
|
3324
|
+
|
3325
|
+
method_type = method_type.subst(subst)
|
3326
|
+
|
3327
|
+
node_type, constr = constr.synthesize(arg.node)
|
3328
|
+
|
3329
|
+
unless constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success?
|
3330
|
+
errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
|
3331
|
+
node: node,
|
3332
|
+
method_type: method_type
|
3333
|
+
)
|
3362
3334
|
end
|
3363
3335
|
end
|
3364
3336
|
end
|
@@ -3391,6 +3363,18 @@ module Steep
|
|
3391
3363
|
]
|
3392
3364
|
end
|
3393
3365
|
|
3366
|
+
def type_check_argument(node, receiver_type:, type:, constraints:, report_node: node, errors:)
|
3367
|
+
check(node, type, constraints: constraints) do |expected, actual, result|
|
3368
|
+
errors << Diagnostic::Ruby::ArgumentTypeMismatch.new(
|
3369
|
+
node: report_node,
|
3370
|
+
receiver_type: receiver_type,
|
3371
|
+
expected: expected,
|
3372
|
+
actual: actual,
|
3373
|
+
result: result
|
3374
|
+
)
|
3375
|
+
end
|
3376
|
+
end
|
3377
|
+
|
3394
3378
|
def type_block_without_hint(node:, block_annotations:, block_params:, block_body:, &block)
|
3395
3379
|
unless block_params
|
3396
3380
|
typing.add_error(
|
@@ -3531,68 +3515,6 @@ module Steep
|
|
3531
3515
|
end
|
3532
3516
|
end
|
3533
3517
|
|
3534
|
-
def self.parameter_types(nodes, type)
|
3535
|
-
nodes = nodes.dup
|
3536
|
-
|
3537
|
-
env = {}
|
3538
|
-
|
3539
|
-
type.params.required.each do |type|
|
3540
|
-
a = nodes.first
|
3541
|
-
if a&.type == :arg
|
3542
|
-
env[a.children.first] = type
|
3543
|
-
nodes.shift
|
3544
|
-
else
|
3545
|
-
break
|
3546
|
-
end
|
3547
|
-
end
|
3548
|
-
|
3549
|
-
type.params.optional.each do |type|
|
3550
|
-
a = nodes.first
|
3551
|
-
|
3552
|
-
if a&.type == :optarg
|
3553
|
-
env[a.children.first] = type
|
3554
|
-
nodes.shift
|
3555
|
-
else
|
3556
|
-
break
|
3557
|
-
end
|
3558
|
-
end
|
3559
|
-
|
3560
|
-
if type.params.rest
|
3561
|
-
a = nodes.first
|
3562
|
-
if a&.type == :restarg
|
3563
|
-
env[a.children.first] = AST::Builtin::Array.instance_type(type.params.rest)
|
3564
|
-
nodes.shift
|
3565
|
-
end
|
3566
|
-
end
|
3567
|
-
|
3568
|
-
nodes.each do |node|
|
3569
|
-
if node.type == :kwarg
|
3570
|
-
name = node.children[0]
|
3571
|
-
ty = type.params.required_keywords[name]
|
3572
|
-
env[name] = ty if ty
|
3573
|
-
end
|
3574
|
-
|
3575
|
-
if node.type == :kwoptarg
|
3576
|
-
name = node.children[0]
|
3577
|
-
ty = type.params.optional_keywords[name]
|
3578
|
-
env[name] = ty if ty
|
3579
|
-
end
|
3580
|
-
|
3581
|
-
if node.type == :kwrestarg
|
3582
|
-
ty = type.params.rest_keywords
|
3583
|
-
if ty
|
3584
|
-
env[node.children[0]] = AST::Builtin::Hash.instance_type(AST::Builtin::Symbol.instance_type, ty)
|
3585
|
-
end
|
3586
|
-
end
|
3587
|
-
end
|
3588
|
-
|
3589
|
-
env
|
3590
|
-
end
|
3591
|
-
|
3592
|
-
def self.valid_parameter_env?(env, nodes, params)
|
3593
|
-
env.size == nodes.size && env.size == params.size
|
3594
|
-
end
|
3595
|
-
|
3596
3518
|
def current_namespace
|
3597
3519
|
module_context&.current_namespace || AST::Namespace.root
|
3598
3520
|
end
|
@@ -3700,25 +3622,6 @@ module Steep
|
|
3700
3622
|
end
|
3701
3623
|
end
|
3702
3624
|
|
3703
|
-
def flatten_const_name(node)
|
3704
|
-
path = []
|
3705
|
-
|
3706
|
-
while node
|
3707
|
-
case node.type
|
3708
|
-
when :const, :casgn
|
3709
|
-
path.unshift(node.children[1])
|
3710
|
-
node = node.children[0]
|
3711
|
-
when :cbase
|
3712
|
-
path.unshift("")
|
3713
|
-
break
|
3714
|
-
else
|
3715
|
-
return nil
|
3716
|
-
end
|
3717
|
-
end
|
3718
|
-
|
3719
|
-
path.join("::").to_sym
|
3720
|
-
end
|
3721
|
-
|
3722
3625
|
def fallback_to_any(node)
|
3723
3626
|
if block_given?
|
3724
3627
|
typing.add_error yield
|
@@ -3760,16 +3663,6 @@ module Steep
|
|
3760
3663
|
Pair.new(type: AST::Builtin.any_type, constr: self)
|
3761
3664
|
end
|
3762
3665
|
|
3763
|
-
def fallback_any_rec(node)
|
3764
|
-
fallback_to_any(node) unless typing.has_type?(node)
|
3765
|
-
|
3766
|
-
each_child_node(node) do |child|
|
3767
|
-
fallback_any_rec(child)
|
3768
|
-
end
|
3769
|
-
|
3770
|
-
typing.type_of(node: node)
|
3771
|
-
end
|
3772
|
-
|
3773
3666
|
def unwrap(type)
|
3774
3667
|
expand_alias(type) do |expanded|
|
3775
3668
|
case
|
@@ -3782,19 +3675,6 @@ module Steep
|
|
3782
3675
|
end
|
3783
3676
|
end
|
3784
3677
|
|
3785
|
-
def self.value_variables(node)
|
3786
|
-
case node&.type
|
3787
|
-
when :lvar
|
3788
|
-
Set.new([node.children.first])
|
3789
|
-
when :lvasgn
|
3790
|
-
Set.new([node.children.first]) + value_variables(node.children[1])
|
3791
|
-
when :begin
|
3792
|
-
value_variables(node.children.last)
|
3793
|
-
else
|
3794
|
-
Set.new
|
3795
|
-
end
|
3796
|
-
end
|
3797
|
-
|
3798
3678
|
def deep_expand_alias(type, &block)
|
3799
3679
|
checker.factory.deep_expand_alias(type, &block)
|
3800
3680
|
end
|
@@ -3841,24 +3721,6 @@ module Steep
|
|
3841
3721
|
end
|
3842
3722
|
end
|
3843
3723
|
|
3844
|
-
def select_super_type(sub_type, super_type)
|
3845
|
-
if super_type
|
3846
|
-
result = check_relation(sub_type: sub_type, super_type: super_type)
|
3847
|
-
|
3848
|
-
if result.success?
|
3849
|
-
super_type
|
3850
|
-
else
|
3851
|
-
if block_given?
|
3852
|
-
yield result
|
3853
|
-
else
|
3854
|
-
sub_type
|
3855
|
-
end
|
3856
|
-
end
|
3857
|
-
else
|
3858
|
-
sub_type
|
3859
|
-
end
|
3860
|
-
end
|
3861
|
-
|
3862
3724
|
def to_instance_type(type, args: nil)
|
3863
3725
|
args = args || case type
|
3864
3726
|
when AST::Types::Name::Singleton
|
@@ -3870,16 +3732,35 @@ module Steep
|
|
3870
3732
|
AST::Types::Name::Instance.new(name: type.name, args: args)
|
3871
3733
|
end
|
3872
3734
|
|
3735
|
+
def try_tuple_type!(node, hint: nil)
|
3736
|
+
if node.type == :array && (hint.nil? || hint.is_a?(AST::Types::Tuple))
|
3737
|
+
node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
|
3738
|
+
|
3739
|
+
typing.new_child(node_range) do |child_typing|
|
3740
|
+
if pair = with_new_typing(child_typing).try_tuple_type(node, hint)
|
3741
|
+
return pair.with(constr: pair.constr.save_typing)
|
3742
|
+
end
|
3743
|
+
end
|
3744
|
+
end
|
3745
|
+
|
3746
|
+
synthesize(node, hint: hint)
|
3747
|
+
end
|
3748
|
+
|
3873
3749
|
def try_tuple_type(node, hint)
|
3874
|
-
if
|
3875
|
-
|
3750
|
+
if hint
|
3751
|
+
if node.children.size != hint.types.size
|
3752
|
+
return
|
3753
|
+
end
|
3876
3754
|
end
|
3877
3755
|
|
3878
3756
|
constr = self
|
3879
3757
|
element_types = []
|
3880
3758
|
|
3881
3759
|
each_child_node(node).with_index do |child, index|
|
3882
|
-
|
3760
|
+
child_hint = if hint
|
3761
|
+
hint.types[index]
|
3762
|
+
end
|
3763
|
+
type, constr = constr.synthesize(child, hint: child_hint)
|
3883
3764
|
element_types << type
|
3884
3765
|
end
|
3885
3766
|
|
@@ -3911,55 +3792,152 @@ module Steep
|
|
3911
3792
|
constr.add_typing(node, type: AST::Builtin::Array.instance_type(element_type))
|
3912
3793
|
end
|
3913
3794
|
|
3914
|
-
|
3915
|
-
|
3795
|
+
# Try to give record type to hash_node.
|
3796
|
+
#
|
3797
|
+
# Returns nil when it cannot have a record type.
|
3798
|
+
# `record_type` can be nil when the keys are not specified.
|
3799
|
+
#
|
3800
|
+
def type_hash_record(hash_node, record_type)
|
3801
|
+
raise unless hash_node.type == :hash
|
3802
|
+
|
3803
|
+
constr = self
|
3804
|
+
|
3805
|
+
if record_type
|
3806
|
+
elements = record_type.elements.dup
|
3807
|
+
else
|
3808
|
+
elements = {}
|
3809
|
+
end
|
3810
|
+
|
3811
|
+
elems = {}
|
3812
|
+
|
3813
|
+
each_child_node(hash_node) do |child|
|
3814
|
+
if child.type == :pair
|
3815
|
+
case child.children[0].type
|
3816
|
+
when :sym, :str, :int
|
3817
|
+
key_node = child.children[0]
|
3818
|
+
value_node = child.children[1]
|
3819
|
+
|
3820
|
+
key = key_node.children[0]
|
3821
|
+
|
3822
|
+
_, constr = constr.synthesize(key_node, hint: AST::Types::Literal.new(value: key))
|
3823
|
+
value_type, constr = constr.synthesize(value_node, hint: elements[key])
|
3824
|
+
|
3825
|
+
elems[key] = value_type
|
3826
|
+
else
|
3827
|
+
return
|
3828
|
+
end
|
3829
|
+
else
|
3830
|
+
return
|
3831
|
+
end
|
3832
|
+
end
|
3833
|
+
|
3834
|
+
type = AST::Types::Record.new(elements: elems)
|
3835
|
+
constr.add_typing(hash_node, type: type)
|
3836
|
+
end
|
3837
|
+
|
3838
|
+
# Give hash_node a type based on hint.
|
3839
|
+
#
|
3840
|
+
# * When hint is Record type, it may have record type.
|
3841
|
+
# * When hint is union type, it tries recursively with the union cases.
|
3842
|
+
# * Otherwise, it tries to be a hash instance.
|
3843
|
+
#
|
3844
|
+
def type_hash(hash_node, hint:)
|
3845
|
+
hint = deep_expand_alias(hint)
|
3846
|
+
range = hash_node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
|
3916
3847
|
|
3917
3848
|
case hint
|
3918
3849
|
when AST::Types::Record
|
3919
|
-
|
3920
|
-
|
3921
|
-
|
3850
|
+
with_child_typing(range: range) do |constr|
|
3851
|
+
pair = constr.type_hash_record(hash_node, hint)
|
3852
|
+
if pair
|
3853
|
+
return pair.with(constr: pair.constr.save_typing)
|
3854
|
+
end
|
3855
|
+
end
|
3856
|
+
when AST::Types::Union
|
3857
|
+
pair = pick_one_of(hint.types, range: range) do |type, constr|
|
3858
|
+
constr.type_hash(hash_node, hint: type)
|
3859
|
+
end
|
3922
3860
|
|
3923
|
-
|
3924
|
-
|
3925
|
-
|
3926
|
-
|
3861
|
+
if pair
|
3862
|
+
return pair
|
3863
|
+
end
|
3864
|
+
end
|
3927
3865
|
|
3928
|
-
|
3929
|
-
|
3930
|
-
key.children[0]
|
3931
|
-
else
|
3932
|
-
return nil
|
3933
|
-
end
|
3866
|
+
key_types = []
|
3867
|
+
value_types = []
|
3934
3868
|
|
3935
|
-
|
3936
|
-
|
3869
|
+
if AST::Builtin::Hash.instance_type?(hint)
|
3870
|
+
key_hint, value_hint = hint.args
|
3871
|
+
end
|
3937
3872
|
|
3938
|
-
|
3939
|
-
|
3940
|
-
|
3941
|
-
|
3873
|
+
hint_hash = AST::Builtin::Hash.instance_type(
|
3874
|
+
key_hint || AST::Builtin.any_type,
|
3875
|
+
value_hint || AST::Builtin.any_type
|
3876
|
+
)
|
3877
|
+
|
3878
|
+
constr = self
|
3879
|
+
|
3880
|
+
if hash_node.children.empty?
|
3881
|
+
key_types << key_hint if key_hint
|
3882
|
+
value_types << value_hint if value_hint
|
3883
|
+
else
|
3884
|
+
hash_node.children.each do |elem|
|
3885
|
+
case elem.type
|
3886
|
+
when :pair
|
3887
|
+
key_node, value_node = elem.children
|
3888
|
+
key_type, constr = constr.synthesize(key_node, hint: key_hint)
|
3889
|
+
value_type, constr = constr.synthesize(value_node, hint: value_hint)
|
3890
|
+
|
3891
|
+
key_types << key_type
|
3892
|
+
value_types << value_type
|
3893
|
+
when :kwsplat
|
3894
|
+
bypass_splat(elem) do |elem_|
|
3895
|
+
pair = constr.synthesize(elem_, hint: hint_hash)
|
3896
|
+
|
3897
|
+
if AST::Builtin::Hash.instance_type?(pair.type)
|
3898
|
+
key_types << pair.type.args[0]
|
3899
|
+
value_types << pair.type.args[1]
|
3942
3900
|
end
|
3943
3901
|
|
3944
|
-
|
3945
|
-
else
|
3946
|
-
return nil
|
3902
|
+
pair
|
3947
3903
|
end
|
3904
|
+
else
|
3905
|
+
raise
|
3948
3906
|
end
|
3907
|
+
end
|
3908
|
+
end
|
3949
3909
|
|
3950
|
-
|
3910
|
+
key_types.reject! {|ty| ty.is_a?(AST::Types::Any) }
|
3911
|
+
value_types.reject! {|ty| ty.is_a?(AST::Types::Any) }
|
3951
3912
|
|
3952
|
-
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
3958
|
-
|
3913
|
+
key_types << AST::Builtin.any_type if key_types.empty?
|
3914
|
+
value_types << AST::Builtin.any_type if value_types.empty?
|
3915
|
+
|
3916
|
+
hash_type = AST::Builtin::Hash.instance_type(
|
3917
|
+
AST::Types::Union.build(types: key_types),
|
3918
|
+
AST::Types::Union.build(types: value_types)
|
3919
|
+
)
|
3920
|
+
constr.add_typing(hash_node, type: hash_type)
|
3921
|
+
end
|
3922
|
+
|
3923
|
+
def pick_one_of(types, range:)
|
3924
|
+
types.each do |type|
|
3925
|
+
with_child_typing(range: range) do |constr|
|
3926
|
+
type_, constr = yield type, constr
|
3927
|
+
|
3928
|
+
constr.check_relation(sub_type: type_, super_type: type).then do
|
3929
|
+
constr = constr.save_typing
|
3930
|
+
return Pair.new(type: type, constr: constr)
|
3959
3931
|
end
|
3960
3932
|
end
|
3961
|
-
nil
|
3962
3933
|
end
|
3934
|
+
|
3935
|
+
nil
|
3936
|
+
end
|
3937
|
+
|
3938
|
+
def save_typing
|
3939
|
+
typing.save!
|
3940
|
+
with_new_typing(typing.parent)
|
3963
3941
|
end
|
3964
3942
|
end
|
3965
3943
|
end
|