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