steep 0.21.0 → 0.27.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -1
- data/Gemfile +7 -0
- data/bin/steep-prof +16 -0
- data/lib/steep/ast/types.rb +5 -3
- data/lib/steep/ast/types/any.rb +1 -3
- data/lib/steep/ast/types/boolean.rb +1 -3
- data/lib/steep/ast/types/bot.rb +1 -3
- data/lib/steep/ast/types/class.rb +2 -2
- data/lib/steep/ast/types/factory.rb +58 -16
- data/lib/steep/ast/types/helper.rb +6 -0
- data/lib/steep/ast/types/instance.rb +2 -2
- data/lib/steep/ast/types/intersection.rb +8 -4
- data/lib/steep/ast/types/literal.rb +5 -3
- data/lib/steep/ast/types/name.rb +13 -9
- data/lib/steep/ast/types/nil.rb +1 -3
- data/lib/steep/ast/types/proc.rb +5 -2
- data/lib/steep/ast/types/record.rb +9 -4
- data/lib/steep/ast/types/self.rb +1 -1
- data/lib/steep/ast/types/top.rb +1 -3
- data/lib/steep/ast/types/tuple.rb +5 -3
- data/lib/steep/ast/types/union.rb +11 -3
- data/lib/steep/ast/types/var.rb +2 -2
- data/lib/steep/ast/types/void.rb +1 -3
- data/lib/steep/drivers/check.rb +4 -0
- data/lib/steep/interface/method_type.rb +48 -18
- data/lib/steep/interface/substitution.rb +32 -2
- data/lib/steep/project/target.rb +17 -3
- data/lib/steep/server/base_worker.rb +4 -3
- data/lib/steep/server/master.rb +3 -1
- data/lib/steep/server/signature_worker.rb +3 -0
- data/lib/steep/signature/errors.rb +28 -0
- data/lib/steep/signature/validator.rb +11 -1
- data/lib/steep/source.rb +2 -1
- data/lib/steep/subtyping/check.rb +38 -21
- data/lib/steep/type_construction.rb +446 -181
- data/lib/steep/type_inference/constant_env.rb +1 -1
- data/lib/steep/type_inference/context.rb +8 -0
- data/lib/steep/type_inference/context_array.rb +4 -3
- data/lib/steep/type_inference/logic.rb +31 -0
- data/lib/steep/typing.rb +7 -0
- data/lib/steep/version.rb +1 -1
- data/smoke/hash/d.rb +1 -1
- data/steep.gemspec +1 -8
- metadata +5 -88
data/lib/steep/source.rb
CHANGED
@@ -79,6 +79,7 @@ module Steep
|
|
79
79
|
end
|
80
80
|
|
81
81
|
mapping = {}
|
82
|
+
|
82
83
|
construct_mapping(node: node, annotations: annotations, mapping: mapping)
|
83
84
|
|
84
85
|
annotations.each do |annot|
|
@@ -185,7 +186,7 @@ module Steep
|
|
185
186
|
construct_mapping(node: node.children[0], annotations: annotations, mapping: mapping, line_range: nil)
|
186
187
|
end
|
187
188
|
|
188
|
-
if node.
|
189
|
+
if node.children.last
|
189
190
|
else_node = node.children.last
|
190
191
|
else_start = node.loc.else.last_line
|
191
192
|
else_end = node.loc.end.line
|
@@ -180,15 +180,6 @@ module Steep
|
|
180
180
|
constraints: constraints
|
181
181
|
)
|
182
182
|
|
183
|
-
when relation.sub_type.is_a?(AST::Types::Literal)
|
184
|
-
check(
|
185
|
-
Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type),
|
186
|
-
self_type: self_type,
|
187
|
-
assumption: assumption,
|
188
|
-
trace: trace,
|
189
|
-
constraints: constraints
|
190
|
-
)
|
191
|
-
|
192
183
|
when relation.sub_type.is_a?(AST::Types::Union)
|
193
184
|
results = relation.sub_type.types.map do |sub_type|
|
194
185
|
check(Relation.new(sub_type: sub_type, super_type: relation.super_type),
|
@@ -311,10 +302,9 @@ module Steep
|
|
311
302
|
when relation.sub_type.is_a?(AST::Types::Tuple) && relation.super_type.is_a?(AST::Types::Tuple)
|
312
303
|
if relation.sub_type.types.size >= relation.super_type.types.size
|
313
304
|
pairs = relation.sub_type.types.take(relation.super_type.types.size).zip(relation.super_type.types)
|
314
|
-
results = pairs.
|
305
|
+
results = pairs.map do |t1, t2|
|
315
306
|
relation = Relation.new(sub_type: t1, super_type: t2)
|
316
|
-
|
317
|
-
check(relation.flip, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)]
|
307
|
+
check(relation, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)
|
318
308
|
end
|
319
309
|
|
320
310
|
if results.all?(&:success?)
|
@@ -327,16 +317,17 @@ module Steep
|
|
327
317
|
trace: trace)
|
328
318
|
end
|
329
319
|
|
330
|
-
when relation.sub_type.is_a?(AST::Types::Tuple) && relation.super_type
|
331
|
-
|
332
|
-
|
320
|
+
when relation.sub_type.is_a?(AST::Types::Tuple) && AST::Builtin::Array.instance_type?(relation.super_type)
|
321
|
+
tuple_element_type = AST::Types::Union.build(
|
322
|
+
types: relation.sub_type.types,
|
323
|
+
location: relation.sub_type.location
|
324
|
+
)
|
333
325
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
constraints: constraints)
|
326
|
+
check(Relation.new(sub_type: tuple_element_type, super_type: relation.super_type.args[0]),
|
327
|
+
self_type: self_type,
|
328
|
+
assumption: assumption,
|
329
|
+
trace: trace,
|
330
|
+
constraints: constraints)
|
340
331
|
|
341
332
|
when relation.sub_type.is_a?(AST::Types::Record) && relation.super_type.is_a?(AST::Types::Record)
|
342
333
|
if Set.new(relation.sub_type.elements.keys).superset?(Set.new(relation.super_type.elements.keys))
|
@@ -369,6 +360,32 @@ module Steep
|
|
369
360
|
trace: trace,
|
370
361
|
constraints: constraints)
|
371
362
|
|
363
|
+
when relation.super_type.is_a?(AST::Types::Literal)
|
364
|
+
case
|
365
|
+
when relation.super_type.value == true && AST::Builtin::TrueClass.instance_type?(relation.sub_type)
|
366
|
+
success(constraints: constraints)
|
367
|
+
when relation.super_type.value == false && AST::Builtin::FalseClass.instance_type?(relation.sub_type)
|
368
|
+
success(constraints: constraints)
|
369
|
+
else
|
370
|
+
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
371
|
+
trace: trace)
|
372
|
+
end
|
373
|
+
|
374
|
+
when relation.super_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.sub_type)
|
375
|
+
success(constraints: constraints)
|
376
|
+
|
377
|
+
when relation.sub_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.super_type)
|
378
|
+
success(constraints: constraints)
|
379
|
+
|
380
|
+
when relation.sub_type.is_a?(AST::Types::Literal)
|
381
|
+
check(
|
382
|
+
Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type),
|
383
|
+
self_type: self_type,
|
384
|
+
assumption: assumption,
|
385
|
+
trace: trace,
|
386
|
+
constraints: constraints
|
387
|
+
)
|
388
|
+
|
372
389
|
else
|
373
390
|
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
374
391
|
trace: trace)
|
@@ -638,7 +638,8 @@ module Steep
|
|
638
638
|
when :__skip__
|
639
639
|
add_typing(node, type: AST::Builtin.any_type)
|
640
640
|
else
|
641
|
-
|
641
|
+
hint ||= context.lvar_env.declared_types[name]&.type
|
642
|
+
rhs_result = synthesize(rhs, hint: hint)
|
642
643
|
|
643
644
|
constr = rhs_result.constr.update_lvar_env do |lvar_env|
|
644
645
|
lvar_env.assign(name, node: node, type: rhs_result.type) do |declared_type, actual_type, result|
|
@@ -743,6 +744,23 @@ module Steep
|
|
743
744
|
|
744
745
|
constr.add_typing(node, type: type)
|
745
746
|
|
747
|
+
when :cvasgn
|
748
|
+
var_node = lhs.updated(:cvar)
|
749
|
+
send_node = rhs.updated(:send, [var_node, op, rhs])
|
750
|
+
new_node = node.updated(:cvasgn, [lhs.children[0], send_node])
|
751
|
+
|
752
|
+
type, constr = synthesize(new_node, hint: hint)
|
753
|
+
|
754
|
+
constr.add_typing(node, type: type)
|
755
|
+
|
756
|
+
when :send
|
757
|
+
new_rhs = rhs.updated(:send, [lhs, node.children[1], node.children[2]])
|
758
|
+
new_node = lhs.updated(:send, [lhs.children[0], :"#{lhs.children[1]}=", *lhs.children.drop(2), new_rhs])
|
759
|
+
|
760
|
+
type, constr = synthesize(new_node, hint: hint)
|
761
|
+
|
762
|
+
constr.add_typing(node, type: type)
|
763
|
+
|
746
764
|
else
|
747
765
|
Steep.logger.error("Unexpected op_asgn lhs: #{lhs.type}")
|
748
766
|
|
@@ -810,7 +828,7 @@ module Steep
|
|
810
828
|
new.typing.add_context_for_body(node, context: new.context)
|
811
829
|
|
812
830
|
each_child_node(args_node) do |arg|
|
813
|
-
new.synthesize(arg)
|
831
|
+
_, new = new.synthesize(arg)
|
814
832
|
end
|
815
833
|
|
816
834
|
body_pair = if body_node
|
@@ -998,11 +1016,17 @@ module Steep
|
|
998
1016
|
yield_self do
|
999
1017
|
var = node.children[0]
|
1000
1018
|
type = context.lvar_env[var.name]
|
1001
|
-
|
1019
|
+
|
1020
|
+
if type
|
1021
|
+
add_typing(node, type: type)
|
1022
|
+
else
|
1002
1023
|
type = AST::Builtin.any_type
|
1003
|
-
|
1024
|
+
if context&.method_context&.method_type
|
1025
|
+
Steep.logger.error { "Unknown arg type: #{node}" }
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
lvasgn(node, type)
|
1004
1029
|
end
|
1005
|
-
add_typing(node, type: type)
|
1006
1030
|
end
|
1007
1031
|
|
1008
1032
|
when :optarg, :kwoptarg
|
@@ -1033,7 +1057,9 @@ module Steep
|
|
1033
1057
|
var = node.children[0]
|
1034
1058
|
type = context.lvar_env[var.name]
|
1035
1059
|
unless type
|
1036
|
-
|
1060
|
+
if context&.method_context&.method_type
|
1061
|
+
Steep.logger.error { "Unknown variable: #{node}" }
|
1062
|
+
end
|
1037
1063
|
typing.add_error Errors::FallbackAny.new(node: node)
|
1038
1064
|
type = AST::Builtin::Array.instance_type(AST::Builtin.any_type)
|
1039
1065
|
end
|
@@ -1046,7 +1072,9 @@ module Steep
|
|
1046
1072
|
var = node.children[0]
|
1047
1073
|
type = context.lvar_env[var.name]
|
1048
1074
|
unless type
|
1049
|
-
|
1075
|
+
if context&.method_context&.method_type
|
1076
|
+
Steep.logger.error { "Unknown variable: #{node}" }
|
1077
|
+
end
|
1050
1078
|
typing.add_error Errors::FallbackAny.new(node: node)
|
1051
1079
|
type = AST::Builtin::Hash.instance_type(AST::Builtin::Symbol.instance_type, AST::Builtin.any_type)
|
1052
1080
|
end
|
@@ -1062,7 +1090,7 @@ module Steep
|
|
1062
1090
|
|
1063
1091
|
when :int
|
1064
1092
|
yield_self do
|
1065
|
-
literal_type =
|
1093
|
+
literal_type = test_literal_type(node.children[0], hint)
|
1066
1094
|
|
1067
1095
|
if literal_type
|
1068
1096
|
add_typing(node, type: literal_type)
|
@@ -1073,7 +1101,7 @@ module Steep
|
|
1073
1101
|
|
1074
1102
|
when :sym
|
1075
1103
|
yield_self do
|
1076
|
-
literal_type =
|
1104
|
+
literal_type = test_literal_type(node.children[0], hint)
|
1077
1105
|
|
1078
1106
|
if literal_type
|
1079
1107
|
add_typing(node, type: literal_type)
|
@@ -1084,7 +1112,7 @@ module Steep
|
|
1084
1112
|
|
1085
1113
|
when :str
|
1086
1114
|
yield_self do
|
1087
|
-
literal_type =
|
1115
|
+
literal_type = test_literal_type(node.children[0], hint)
|
1088
1116
|
|
1089
1117
|
if literal_type
|
1090
1118
|
add_typing(node, type: literal_type)
|
@@ -1094,7 +1122,13 @@ module Steep
|
|
1094
1122
|
end
|
1095
1123
|
|
1096
1124
|
when :true, :false
|
1097
|
-
|
1125
|
+
ty = node.type == :true ? AST::Types::Literal.new(value: true) : AST::Types::Literal.new(value: false)
|
1126
|
+
|
1127
|
+
if hint && check_relation(sub_type: ty, super_type: hint).success?
|
1128
|
+
add_typing(node, type: hint)
|
1129
|
+
else
|
1130
|
+
add_typing(node, type: AST::Types::Boolean.new)
|
1131
|
+
end
|
1098
1132
|
|
1099
1133
|
when :hash
|
1100
1134
|
yield_self do
|
@@ -1294,69 +1328,45 @@ module Steep
|
|
1294
1328
|
when :array
|
1295
1329
|
yield_self do
|
1296
1330
|
if node.children.empty?
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
end
|
1304
|
-
end
|
1305
|
-
|
1306
|
-
add_typing(node, type: array_type || AST::Builtin::Array.instance_type(AST::Builtin.any_type))
|
1307
|
-
else
|
1308
|
-
is_tuple = nil
|
1309
|
-
|
1310
|
-
expand_alias(hint) do |hint|
|
1311
|
-
is_tuple = hint.is_a?(AST::Types::Tuple)
|
1312
|
-
is_tuple &&= node.children.all? {|child| child.type != :splat}
|
1313
|
-
is_tuple &&= node.children.size >= hint.types.size
|
1314
|
-
is_tuple &&= hint.types.map.with_index do |child_type, index|
|
1315
|
-
child_node = node.children[index]
|
1316
|
-
[synthesize(child_node, hint: child_type).type, child_type]
|
1317
|
-
end.all? do |node_type, hint_type|
|
1318
|
-
result = check_relation(sub_type: node_type, super_type: hint_type)
|
1319
|
-
result.success?
|
1331
|
+
if hint
|
1332
|
+
array = AST::Builtin::Array.instance_type(AST::Builtin.any_type)
|
1333
|
+
if check_relation(sub_type: array, super_type: hint).success?
|
1334
|
+
add_typing node, type: hint
|
1335
|
+
else
|
1336
|
+
add_typing node, type: array
|
1320
1337
|
end
|
1321
|
-
end
|
1322
|
-
|
1323
|
-
if is_tuple
|
1324
|
-
array_type = hint
|
1325
1338
|
else
|
1326
|
-
|
1327
|
-
|
1339
|
+
typing.add_error Errors::FallbackAny.new(node: node)
|
1340
|
+
add_typing node, type: AST::Builtin::Array.instance_type(AST::Builtin.any_type)
|
1341
|
+
end
|
1342
|
+
else
|
1343
|
+
node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
|
1344
|
+
|
1345
|
+
if hint && !(tuples = select_flatten_types(hint) {|type| type.is_a?(AST::Types::Tuple) }).empty?
|
1346
|
+
tuples.each do |tuple|
|
1347
|
+
typing.new_child(node_range) do |child_typing|
|
1348
|
+
pair = with_new_typing(child_typing).try_tuple_type(node, tuple)
|
1349
|
+
if pair && pair.constr.check_relation(sub_type: pair.type, super_type: hint).success?
|
1350
|
+
child_typing.save!
|
1351
|
+
return pair.with(constr: pair.constr.with_new_typing(typing))
|
1352
|
+
end
|
1353
|
+
end
|
1328
1354
|
end
|
1355
|
+
end
|
1329
1356
|
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
ty.types
|
1338
|
-
else
|
1339
|
-
[ty]
|
1340
|
-
end
|
1341
|
-
end
|
1342
|
-
end.map do |type|
|
1343
|
-
case
|
1344
|
-
when AST::Builtin::Array.instance_type?(type)
|
1345
|
-
type.args.first
|
1346
|
-
when AST::Builtin::Range.instance_type?(type)
|
1347
|
-
type.args.first
|
1348
|
-
else
|
1349
|
-
type
|
1350
|
-
end
|
1357
|
+
if hint && !(arrays = select_flatten_types(hint) {|type| AST::Builtin::Array.instance_type?(type) }).empty?
|
1358
|
+
arrays.each do |array|
|
1359
|
+
typing.new_child(node_range) do |child_typing|
|
1360
|
+
pair = with_new_typing(child_typing).try_array_type(node, array)
|
1361
|
+
if pair.constr.check_relation(sub_type: pair.type, super_type: hint).success?
|
1362
|
+
child_typing.save!
|
1363
|
+
return pair.with(constr: pair.constr.with_new_typing(typing))
|
1351
1364
|
end
|
1352
|
-
else
|
1353
|
-
[select_super_type(synthesize(e, hint: element_hint).type, element_hint)]
|
1354
1365
|
end
|
1355
1366
|
end
|
1356
|
-
array_type = AST::Builtin::Array.instance_type(AST::Types::Union.build(types: element_types))
|
1357
1367
|
end
|
1358
1368
|
|
1359
|
-
|
1369
|
+
try_array_type(node, nil)
|
1360
1370
|
end
|
1361
1371
|
end
|
1362
1372
|
|
@@ -1665,6 +1675,49 @@ module Steep
|
|
1665
1675
|
when :masgn
|
1666
1676
|
type_masgn(node)
|
1667
1677
|
|
1678
|
+
when :for
|
1679
|
+
yield_self do
|
1680
|
+
asgn, collection, body = node.children
|
1681
|
+
|
1682
|
+
collection_type, constr = synthesize(collection)
|
1683
|
+
collection_type = expand_self(collection_type)
|
1684
|
+
|
1685
|
+
var_type = case collection_type
|
1686
|
+
when AST::Types::Any
|
1687
|
+
AST::Types::Any.new
|
1688
|
+
else
|
1689
|
+
each = checker.factory.interface(collection_type, private: true).methods[:each]
|
1690
|
+
method_type = (each&.types || []).find {|type| type.block && type.block.type.params.first_param }
|
1691
|
+
method_type&.yield_self do |method_type|
|
1692
|
+
method_type.block.type.params.first_param&.type
|
1693
|
+
end
|
1694
|
+
end
|
1695
|
+
|
1696
|
+
if var_type
|
1697
|
+
if body
|
1698
|
+
body_constr = constr.with_updated_context(
|
1699
|
+
lvar_env: constr.context.lvar_env.assign(asgn.children[0].name, node: asgn, type: var_type)
|
1700
|
+
)
|
1701
|
+
|
1702
|
+
typing.add_context_for_body(node, context: body_constr.context)
|
1703
|
+
_, _, body_context = body_constr.synthesize(body)
|
1704
|
+
|
1705
|
+
constr = constr.update_lvar_env {|env| env.join(constr.context.lvar_env, body_context.lvar_env) }
|
1706
|
+
else
|
1707
|
+
constr = self
|
1708
|
+
end
|
1709
|
+
|
1710
|
+
add_typing(node, type: collection_type, constr: constr)
|
1711
|
+
else
|
1712
|
+
fallback_to_any(node) do
|
1713
|
+
Errors::NoMethod.new(
|
1714
|
+
node: node,
|
1715
|
+
method: :each,
|
1716
|
+
type: collection_type
|
1717
|
+
)
|
1718
|
+
end
|
1719
|
+
end
|
1720
|
+
end
|
1668
1721
|
when :while, :until
|
1669
1722
|
yield_self do
|
1670
1723
|
cond, body = node.children
|
@@ -1746,9 +1799,36 @@ module Steep
|
|
1746
1799
|
|
1747
1800
|
when :or_asgn, :and_asgn
|
1748
1801
|
yield_self do
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1802
|
+
asgn, rhs = node.children
|
1803
|
+
|
1804
|
+
case asgn.type
|
1805
|
+
when :lvasgn
|
1806
|
+
type, constr = synthesize(rhs, hint: hint)
|
1807
|
+
constr.lvasgn(asgn, type)
|
1808
|
+
when :ivasgn
|
1809
|
+
type, constr = synthesize(rhs, hint: hint)
|
1810
|
+
constr.ivasgn(asgn, type)
|
1811
|
+
when :send
|
1812
|
+
rhs_ = node.updated(:send,
|
1813
|
+
[
|
1814
|
+
asgn.children[0],
|
1815
|
+
:"#{asgn.children[1]}=",
|
1816
|
+
asgn.children[2],
|
1817
|
+
rhs
|
1818
|
+
])
|
1819
|
+
node_type = case node.type
|
1820
|
+
when :or_asgn
|
1821
|
+
:or
|
1822
|
+
when :and_asgn
|
1823
|
+
:and
|
1824
|
+
end
|
1825
|
+
node_ = node.updated(node_type, [asgn, rhs_])
|
1826
|
+
|
1827
|
+
synthesize(node_, hint: hint)
|
1828
|
+
else
|
1829
|
+
Steep.logger.error { "#{node.type} with #{asgn.type} lhs is not supported"}
|
1830
|
+
fallback_to_any(node)
|
1831
|
+
end
|
1752
1832
|
end
|
1753
1833
|
|
1754
1834
|
when :defined?
|
@@ -1824,9 +1904,50 @@ module Steep
|
|
1824
1904
|
add_typing node, type: AST::Builtin.any_type
|
1825
1905
|
end
|
1826
1906
|
|
1827
|
-
when :
|
1907
|
+
when :cvasgn
|
1908
|
+
name, rhs = node.children
|
1909
|
+
|
1910
|
+
type, constr = synthesize(rhs, hint: hint)
|
1911
|
+
|
1912
|
+
var_type = if module_context&.class_variables
|
1913
|
+
module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
|
1914
|
+
end
|
1915
|
+
|
1916
|
+
if var_type
|
1917
|
+
result = constr.check_relation(sub_type: type, super_type: var_type)
|
1918
|
+
|
1919
|
+
if result.success?
|
1920
|
+
add_typing node, type: type, constr: constr
|
1921
|
+
else
|
1922
|
+
fallback_to_any node do
|
1923
|
+
Errors::IncompatibleAssignment.new(node: node,
|
1924
|
+
lhs_type: var_type,
|
1925
|
+
rhs_type: type,
|
1926
|
+
result: result)
|
1927
|
+
end
|
1928
|
+
end
|
1929
|
+
else
|
1930
|
+
fallback_to_any(node)
|
1931
|
+
end
|
1932
|
+
|
1933
|
+
when :cvar
|
1934
|
+
name = node.children[0]
|
1935
|
+
var_type = if module_context&.class_variables
|
1936
|
+
module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
|
1937
|
+
end
|
1938
|
+
|
1939
|
+
if var_type
|
1940
|
+
add_typing node, type: var_type
|
1941
|
+
else
|
1942
|
+
fallback_to_any node
|
1943
|
+
end
|
1944
|
+
|
1945
|
+
when :alias
|
1946
|
+
add_typing node, type: AST::Builtin.nil_type
|
1947
|
+
|
1948
|
+
when :splat
|
1828
1949
|
yield_self do
|
1829
|
-
Steep.logger.
|
1950
|
+
Steep.logger.warn { "Unsupported node #{node.type} (#{node.location.expression.source_buffer.name}:#{node.location.expression.line})" }
|
1830
1951
|
|
1831
1952
|
each_child_node node do |child|
|
1832
1953
|
synthesize(child)
|
@@ -1876,136 +1997,202 @@ module Steep
|
|
1876
1997
|
add_typing(node, type: ivar_type)
|
1877
1998
|
end
|
1878
1999
|
|
2000
|
+
def masgn_lhs?(lhs)
|
2001
|
+
lhs.children.all? do |a|
|
2002
|
+
asgn_type = if a.type == :splat
|
2003
|
+
a.children[0].type
|
2004
|
+
else
|
2005
|
+
a.type
|
2006
|
+
end
|
2007
|
+
asgn_type == :lvasgn || asgn_type == :ivasgn
|
2008
|
+
end
|
2009
|
+
end
|
2010
|
+
|
2011
|
+
def lvasgn(node, type)
|
2012
|
+
name = node.children[0].name
|
2013
|
+
env = context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
|
2014
|
+
typing.add_error(
|
2015
|
+
Errors::IncompatibleAssignment.new(node: node,
|
2016
|
+
lhs_type: declared_type,
|
2017
|
+
rhs_type: type,
|
2018
|
+
result: result)
|
2019
|
+
)
|
2020
|
+
end
|
2021
|
+
|
2022
|
+
add_typing(node, type: type, constr: with_updated_context(lvar_env: env))
|
2023
|
+
end
|
2024
|
+
|
2025
|
+
def ivasgn(node, type)
|
2026
|
+
ivar = node.children[0]
|
2027
|
+
|
2028
|
+
type_env.assign(ivar: ivar, type: type, self_type: self_type) do |error|
|
2029
|
+
case error
|
2030
|
+
when Subtyping::Result::Failure
|
2031
|
+
var_type = type_env.get(ivar: ivar)
|
2032
|
+
typing.add_error(Errors::IncompatibleAssignment.new(node: node,
|
2033
|
+
lhs_type: var_type,
|
2034
|
+
rhs_type: type,
|
2035
|
+
result: error))
|
2036
|
+
when nil
|
2037
|
+
fallback_to_any node
|
2038
|
+
end
|
2039
|
+
end
|
2040
|
+
|
2041
|
+
add_typing(node, type: type)
|
2042
|
+
end
|
2043
|
+
|
1879
2044
|
def type_masgn(node)
|
1880
2045
|
lhs, rhs = node.children
|
1881
2046
|
rhs_pair = synthesize(rhs)
|
1882
|
-
rhs_type =
|
2047
|
+
rhs_type = deep_expand_alias(rhs_pair.type)
|
1883
2048
|
|
1884
2049
|
constr = rhs_pair.constr
|
1885
2050
|
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
2051
|
+
unless masgn_lhs?(lhs)
|
2052
|
+
Steep.logger.error("Unsupported masgn lhs node: only lvasgn, ivasgn, and splat are supported")
|
2053
|
+
_, constr = constr.fallback_to_any(lhs)
|
2054
|
+
return add_typing(node, type: rhs_type, constr: constr)
|
2055
|
+
end
|
1890
2056
|
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
2057
|
+
falseys, truthys = partition_flatten_types(rhs_type) do |type|
|
2058
|
+
type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
|
2059
|
+
end
|
2060
|
+
|
2061
|
+
unwrap_rhs_type = AST::Types::Union.build(types: truthys)
|
2062
|
+
|
2063
|
+
case
|
2064
|
+
when unwrap_rhs_type.is_a?(AST::Types::Tuple) || (rhs.type == :array && rhs.children.none? {|n| n.type == :splat })
|
2065
|
+
tuple_types = if unwrap_rhs_type.is_a?(AST::Types::Tuple)
|
2066
|
+
unwrap_rhs_type.types.dup
|
2067
|
+
else
|
2068
|
+
rhs.children.map do |node|
|
2069
|
+
typing.type_of(node: node)
|
2070
|
+
end
|
2071
|
+
end
|
2072
|
+
|
2073
|
+
assignment_nodes = lhs.children.dup
|
2074
|
+
leading_assignments = []
|
2075
|
+
trailing_assignments = []
|
2076
|
+
|
2077
|
+
until assignment_nodes.empty?
|
2078
|
+
cursor = assignment_nodes.first
|
2079
|
+
|
2080
|
+
if cursor.type == :splat
|
2081
|
+
break
|
2082
|
+
else
|
2083
|
+
leading_assignments << assignment_nodes.shift
|
1911
2084
|
end
|
2085
|
+
end
|
1912
2086
|
|
1913
|
-
|
2087
|
+
until assignment_nodes.empty?
|
2088
|
+
cursor = assignment_nodes.last
|
1914
2089
|
|
1915
|
-
|
1916
|
-
|
2090
|
+
if cursor.type == :splat
|
2091
|
+
break
|
2092
|
+
else
|
2093
|
+
trailing_assignments.unshift assignment_nodes.pop
|
2094
|
+
end
|
2095
|
+
end
|
1917
2096
|
|
1918
|
-
|
1919
|
-
|
2097
|
+
leading_assignments.each do |asgn|
|
2098
|
+
type = tuple_types.first
|
1920
2099
|
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
Errors::IncompatibleAssignment.new(node: lhs,
|
1927
|
-
lhs_type: declared_type,
|
1928
|
-
rhs_type: type,
|
1929
|
-
result: result)
|
1930
|
-
)
|
1931
|
-
end
|
1932
|
-
add_typing(lhs,
|
1933
|
-
type: ty,
|
1934
|
-
constr: ctr.with_updated_context(lvar_env: env)).constr
|
1935
|
-
when :ivasgn
|
1936
|
-
ivar = lhs.children[0]
|
2100
|
+
if type
|
2101
|
+
tuple_types.shift
|
2102
|
+
else
|
2103
|
+
type = AST::Builtin.nil_type
|
2104
|
+
end
|
1937
2105
|
|
1938
|
-
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
result: error))
|
1946
|
-
when nil
|
1947
|
-
fallback_to_any node
|
1948
|
-
end
|
1949
|
-
end
|
2106
|
+
case asgn.type
|
2107
|
+
when :lvasgn
|
2108
|
+
_, constr = constr.lvasgn(asgn, type)
|
2109
|
+
when :ivasgn
|
2110
|
+
_, constr = constr.ivasgn(asgn, type)
|
2111
|
+
end
|
2112
|
+
end
|
1950
2113
|
|
1951
|
-
|
1952
|
-
|
2114
|
+
trailing_assignments.reverse_each do |asgn|
|
2115
|
+
type = tuple_types.last
|
2116
|
+
|
2117
|
+
if type
|
2118
|
+
tuple_types.pop
|
2119
|
+
else
|
2120
|
+
type = AST::Builtin.nil_type
|
1953
2121
|
end
|
1954
2122
|
|
1955
|
-
|
2123
|
+
case asgn.type
|
2124
|
+
when :lvasgn
|
2125
|
+
_, constr = constr.lvasgn(asgn, type)
|
2126
|
+
when :ivasgn
|
2127
|
+
_, constr = constr.ivasgn(asgn, type)
|
2128
|
+
end
|
2129
|
+
end
|
1956
2130
|
|
1957
|
-
|
1958
|
-
|
2131
|
+
element_type = if tuple_types.empty?
|
2132
|
+
AST::Builtin.nil_type
|
2133
|
+
else
|
2134
|
+
AST::Types::Union.build(types: tuple_types)
|
2135
|
+
end
|
2136
|
+
array_type = AST::Builtin::Array.instance_type(element_type)
|
1959
2137
|
|
1960
|
-
|
1961
|
-
|
2138
|
+
assignment_nodes.each do |asgn|
|
2139
|
+
case asgn.type
|
2140
|
+
when :splat
|
2141
|
+
case asgn.children[0].type
|
1962
2142
|
when :lvasgn
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
2143
|
+
_, constr = constr.lvasgn(asgn.children[0], array_type)
|
2144
|
+
when :ivasgn
|
2145
|
+
_, constr = constr.ivasgn(asgn.children[0], array_type)
|
2146
|
+
end
|
2147
|
+
when :lvasgn
|
2148
|
+
_, constr = constr.lvasgn(asgn, element_type)
|
2149
|
+
when :ivasgn
|
2150
|
+
_,constr = constr.ivasgn(asgn, element_type)
|
2151
|
+
end
|
2152
|
+
end
|
1972
2153
|
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
2154
|
+
unless falseys.empty?
|
2155
|
+
constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
|
2156
|
+
end
|
1976
2157
|
|
1977
|
-
|
1978
|
-
ivar = assignment.children[0]
|
2158
|
+
add_typing(node, type: rhs_type, constr: constr)
|
1979
2159
|
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
when nil
|
1989
|
-
fallback_to_any node
|
1990
|
-
end
|
1991
|
-
end
|
2160
|
+
when flatten_union(unwrap_rhs_type).all? {|type| AST::Builtin::Array.instance_type?(type) }
|
2161
|
+
array_elements = flatten_union(unwrap_rhs_type).map {|type| type.args[0] }
|
2162
|
+
element_type = AST::Types::Union.build(types: array_elements + [AST::Builtin.nil_type])
|
2163
|
+
|
2164
|
+
constr = lhs.children.inject(constr) do |constr, assignment|
|
2165
|
+
case assignment.type
|
2166
|
+
when :lvasgn
|
2167
|
+
_, constr = constr.lvasgn(assignment, element_type)
|
1992
2168
|
|
1993
|
-
|
2169
|
+
when :ivasgn
|
2170
|
+
_, constr = constr.ivasgn(assignment, element_type)
|
2171
|
+
when :splat
|
2172
|
+
case assignment.children[0].type
|
2173
|
+
when :lvasgn
|
2174
|
+
_, constr = constr.lvasgn(assignment.children[0], unwrap_rhs_type)
|
2175
|
+
when :ivasgn
|
2176
|
+
_, constr = constr.ivasgn(assignment.children[0], unwrap_rhs_type)
|
2177
|
+
else
|
2178
|
+
raise
|
1994
2179
|
end
|
1995
2180
|
end
|
1996
2181
|
|
1997
|
-
|
1998
|
-
|
1999
|
-
when rhs_type.is_a?(AST::Types::Any)
|
2000
|
-
fallback_to_any(node)
|
2182
|
+
constr
|
2183
|
+
end
|
2001
2184
|
|
2002
|
-
|
2003
|
-
|
2004
|
-
fallback_to_any(node)
|
2185
|
+
unless falseys.empty?
|
2186
|
+
constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
|
2005
2187
|
end
|
2188
|
+
|
2189
|
+
add_typing(node, type: rhs_type, constr: constr)
|
2006
2190
|
else
|
2007
|
-
|
2008
|
-
|
2191
|
+
unless rhs_type.is_a?(AST::Types::Any)
|
2192
|
+
Steep.logger.error("Unsupported masgn rhs type: array or tuple is supported (#{rhs_type})")
|
2193
|
+
end
|
2194
|
+
_, constr = constr.fallback_to_any(lhs)
|
2195
|
+
add_typing(node, type: rhs_type, constr: constr)
|
2009
2196
|
end
|
2010
2197
|
end
|
2011
2198
|
|
@@ -2056,7 +2243,7 @@ module Steep
|
|
2056
2243
|
else
|
2057
2244
|
case expanded_receiver_type = expand_self(receiver_type)
|
2058
2245
|
when AST::Types::Self
|
2059
|
-
Steep.logger.
|
2246
|
+
Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
|
2060
2247
|
fallback_to_any node do
|
2061
2248
|
Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2062
2249
|
end
|
@@ -2999,7 +3186,12 @@ module Steep
|
|
2999
3186
|
|
3000
3187
|
ty = case type
|
3001
3188
|
when AST::Types::Name::Alias
|
3002
|
-
deep_expand_alias(expand_alias(type), recursive: recursive
|
3189
|
+
deep_expand_alias(expand_alias(type), recursive: recursive.union([type]))
|
3190
|
+
when AST::Types::Union
|
3191
|
+
AST::Types::Union.build(
|
3192
|
+
types: type.types.map {|ty| deep_expand_alias(ty, recursive: recursive, &block) },
|
3193
|
+
location: type.location
|
3194
|
+
)
|
3003
3195
|
else
|
3004
3196
|
type
|
3005
3197
|
end
|
@@ -3011,19 +3203,51 @@ module Steep
|
|
3011
3203
|
end
|
3012
3204
|
end
|
3013
3205
|
|
3206
|
+
def flatten_union(type, acc = [])
|
3207
|
+
case type
|
3208
|
+
when AST::Types::Union
|
3209
|
+
type.types.each {|ty| flatten_union(ty, acc) }
|
3210
|
+
else
|
3211
|
+
acc << type
|
3212
|
+
end
|
3213
|
+
|
3214
|
+
acc
|
3215
|
+
end
|
3216
|
+
|
3217
|
+
def select_flatten_types(type, &block)
|
3218
|
+
types = flatten_union(deep_expand_alias(type))
|
3219
|
+
types.select(&block)
|
3220
|
+
end
|
3221
|
+
|
3222
|
+
def partition_flatten_types(type, &block)
|
3223
|
+
types = flatten_union(deep_expand_alias(type))
|
3224
|
+
types.partition(&block)
|
3225
|
+
end
|
3226
|
+
|
3227
|
+
def flatten_array_elements(type)
|
3228
|
+
flatten_union(deep_expand_alias(type)).flat_map do |type|
|
3229
|
+
if AST::Builtin::Array.instance_type?(type)
|
3230
|
+
type.args
|
3231
|
+
else
|
3232
|
+
[type]
|
3233
|
+
end
|
3234
|
+
end
|
3235
|
+
end
|
3236
|
+
|
3014
3237
|
def expand_alias(type, &block)
|
3015
3238
|
checker.factory.expand_alias(type, &block)
|
3016
3239
|
end
|
3017
3240
|
|
3018
3241
|
def test_literal_type(literal, hint)
|
3019
|
-
|
3020
|
-
|
3021
|
-
|
3022
|
-
|
3023
|
-
|
3024
|
-
|
3025
|
-
|
3026
|
-
|
3242
|
+
if hint
|
3243
|
+
case hint
|
3244
|
+
when AST::Types::Any
|
3245
|
+
nil
|
3246
|
+
else
|
3247
|
+
literal_type = AST::Types::Literal.new(value: literal, location: nil)
|
3248
|
+
if check_relation(sub_type: literal_type, super_type: hint).success?
|
3249
|
+
hint
|
3250
|
+
end
|
3027
3251
|
end
|
3028
3252
|
end
|
3029
3253
|
end
|
@@ -3057,6 +3281,47 @@ module Steep
|
|
3057
3281
|
AST::Types::Name::Instance.new(name: type.name, args: args)
|
3058
3282
|
end
|
3059
3283
|
|
3284
|
+
def try_tuple_type(node, hint)
|
3285
|
+
if node.children.size != hint.types.size
|
3286
|
+
return
|
3287
|
+
end
|
3288
|
+
|
3289
|
+
constr = self
|
3290
|
+
element_types = []
|
3291
|
+
|
3292
|
+
each_child_node(node).with_index do |child, index|
|
3293
|
+
type, constr = constr.synthesize(child, hint: hint.types[index])
|
3294
|
+
element_types << type
|
3295
|
+
end
|
3296
|
+
|
3297
|
+
constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
|
3298
|
+
end
|
3299
|
+
|
3300
|
+
def try_array_type(node, hint)
|
3301
|
+
element_hint = hint ? hint.args[0] : nil
|
3302
|
+
|
3303
|
+
constr = self
|
3304
|
+
element_types = []
|
3305
|
+
|
3306
|
+
each_child_node(node) do |child|
|
3307
|
+
case child.type
|
3308
|
+
when :splat
|
3309
|
+
type, constr = constr.synthesize(child.children[0], hint: hint)
|
3310
|
+
if AST::Builtin::Array.instance_type?(type)
|
3311
|
+
element_types << type.args[0]
|
3312
|
+
else
|
3313
|
+
element_types.push(*flatten_array_elements(type))
|
3314
|
+
end
|
3315
|
+
else
|
3316
|
+
type, constr = constr.synthesize(child, hint: element_hint)
|
3317
|
+
element_types << type
|
3318
|
+
end
|
3319
|
+
end
|
3320
|
+
|
3321
|
+
element_type = AST::Types::Union.build(types: element_types)
|
3322
|
+
constr.add_typing(node, type: AST::Builtin::Array.instance_type(element_type))
|
3323
|
+
end
|
3324
|
+
|
3060
3325
|
def try_hash_type(node, hint)
|
3061
3326
|
case hint
|
3062
3327
|
when AST::Types::Record
|