steep 0.21.0 → 0.27.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/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
|