steep 0.24.0 → 0.25.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 +8 -0
- data/lib/steep/ast/types/union.rb +4 -1
- data/lib/steep/drivers/check.rb +4 -0
- data/lib/steep/project/target.rb +5 -2
- data/lib/steep/source.rb +2 -1
- data/lib/steep/subtyping/check.rb +10 -9
- data/lib/steep/type_construction.rb +404 -168
- 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
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c290301da65ed473b092cd6c2ea39eebe02f566124a1fa32e0f420d290513cbf
|
4
|
+
data.tar.gz: ca4fca20e9f3f0b19c57b98d6cdfce0023aeeff8cd0fcd2ee0fc91346e5e0816
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76c3b0c76e303bcc558bf20efeebe3ddaa3caef432f5d325261261f6d8431f5bbd36bc44af9a4a4dd6a90f2db30ac35ca044181b25063890c0e68c5499d7792c
|
7
|
+
data.tar.gz: a5fa8fba718f599806d9d0ad62a66c138261469d41694bb39ebafe1b8736ad255e890c55f0e3b4f180f4e0212f0b65b31b5957b5c337cba42d1129b9e935e577
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.25.0 (2020-08-18)
|
6
|
+
|
7
|
+
* Improve `op_send` typing ([#186](https://github.com/soutaro/steep/pull/186))
|
8
|
+
* Improve `op_asgn` typing ([#189](https://github.com/soutaro/steep/pull/189))
|
9
|
+
* Better multi-assignment support ([#183](https://github.com/soutaro/steep/pull/183), [#184](https://github.com/soutaro/steep/pull/184))
|
10
|
+
* Support for loop and class variables ([#182](https://github.com/soutaro/steep/pull/182))
|
11
|
+
* Fix tuple typing ([#181](https://github.com/soutaro/steep/pull/181))
|
12
|
+
|
5
13
|
## 0.24.0 (2020-08-11)
|
6
14
|
|
7
15
|
* Update RBS to 0.10 ([#180](https://github.com/soutaro/steep/pull/180))
|
data/lib/steep/drivers/check.rb
CHANGED
data/lib/steep/project/target.rb
CHANGED
@@ -172,6 +172,7 @@ module Steep
|
|
172
172
|
timestamp: Time.now
|
173
173
|
)
|
174
174
|
rescue => exn
|
175
|
+
Steep.log_error exn
|
175
176
|
@status = SignatureOtherErrorStatus.new(error: exn, timestamp: Time.now)
|
176
177
|
end
|
177
178
|
end
|
@@ -194,8 +195,10 @@ module Steep
|
|
194
195
|
type_check_sources = []
|
195
196
|
|
196
197
|
target_sources.each do |file|
|
197
|
-
|
198
|
-
|
198
|
+
Steep.logger.tagged("path=#{file.path}") do
|
199
|
+
if file.type_check(check, timestamp)
|
200
|
+
type_check_sources << file
|
201
|
+
end
|
199
202
|
end
|
200
203
|
end
|
201
204
|
|
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
|
@@ -318,16 +318,17 @@ module Steep
|
|
318
318
|
trace: trace)
|
319
319
|
end
|
320
320
|
|
321
|
-
when relation.sub_type.is_a?(AST::Types::Tuple) && relation.super_type
|
322
|
-
|
323
|
-
|
321
|
+
when relation.sub_type.is_a?(AST::Types::Tuple) && AST::Builtin::Array.instance_type?(relation.super_type)
|
322
|
+
tuple_element_type = AST::Types::Union.build(
|
323
|
+
types: relation.sub_type.types,
|
324
|
+
location: relation.sub_type.location
|
325
|
+
)
|
324
326
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
constraints: constraints)
|
327
|
+
check(Relation.new(sub_type: tuple_element_type, super_type: relation.super_type.args[0]),
|
328
|
+
self_type: self_type,
|
329
|
+
assumption: assumption,
|
330
|
+
trace: trace,
|
331
|
+
constraints: constraints)
|
331
332
|
|
332
333
|
when relation.sub_type.is_a?(AST::Types::Record) && relation.super_type.is_a?(AST::Types::Record)
|
333
334
|
if Set.new(relation.sub_type.elements.keys).superset?(Set.new(relation.super_type.elements.keys))
|
@@ -744,6 +744,23 @@ module Steep
|
|
744
744
|
|
745
745
|
constr.add_typing(node, type: type)
|
746
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
|
+
|
747
764
|
else
|
748
765
|
Steep.logger.error("Unexpected op_asgn lhs: #{lhs.type}")
|
749
766
|
|
@@ -811,7 +828,7 @@ module Steep
|
|
811
828
|
new.typing.add_context_for_body(node, context: new.context)
|
812
829
|
|
813
830
|
each_child_node(args_node) do |arg|
|
814
|
-
new.synthesize(arg)
|
831
|
+
_, new = new.synthesize(arg)
|
815
832
|
end
|
816
833
|
|
817
834
|
body_pair = if body_node
|
@@ -999,11 +1016,17 @@ module Steep
|
|
999
1016
|
yield_self do
|
1000
1017
|
var = node.children[0]
|
1001
1018
|
type = context.lvar_env[var.name]
|
1002
|
-
|
1019
|
+
|
1020
|
+
if type
|
1021
|
+
add_typing(node, type: type)
|
1022
|
+
else
|
1003
1023
|
type = AST::Builtin.any_type
|
1004
|
-
|
1024
|
+
if context&.method_context&.method_type
|
1025
|
+
Steep.logger.error { "Unknown arg type: #{node}" }
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
lvasgn(node, type)
|
1005
1029
|
end
|
1006
|
-
add_typing(node, type: type)
|
1007
1030
|
end
|
1008
1031
|
|
1009
1032
|
when :optarg, :kwoptarg
|
@@ -1034,7 +1057,9 @@ module Steep
|
|
1034
1057
|
var = node.children[0]
|
1035
1058
|
type = context.lvar_env[var.name]
|
1036
1059
|
unless type
|
1037
|
-
|
1060
|
+
if context&.method_context&.method_type
|
1061
|
+
Steep.logger.error { "Unknown variable: #{node}" }
|
1062
|
+
end
|
1038
1063
|
typing.add_error Errors::FallbackAny.new(node: node)
|
1039
1064
|
type = AST::Builtin::Array.instance_type(AST::Builtin.any_type)
|
1040
1065
|
end
|
@@ -1047,7 +1072,9 @@ module Steep
|
|
1047
1072
|
var = node.children[0]
|
1048
1073
|
type = context.lvar_env[var.name]
|
1049
1074
|
unless type
|
1050
|
-
|
1075
|
+
if context&.method_context&.method_type
|
1076
|
+
Steep.logger.error { "Unknown variable: #{node}" }
|
1077
|
+
end
|
1051
1078
|
typing.add_error Errors::FallbackAny.new(node: node)
|
1052
1079
|
type = AST::Builtin::Hash.instance_type(AST::Builtin::Symbol.instance_type, AST::Builtin.any_type)
|
1053
1080
|
end
|
@@ -1301,69 +1328,45 @@ module Steep
|
|
1301
1328
|
when :array
|
1302
1329
|
yield_self do
|
1303
1330
|
if node.children.empty?
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
end
|
1311
|
-
end
|
1312
|
-
|
1313
|
-
add_typing(node, type: array_type || AST::Builtin::Array.instance_type(AST::Builtin.any_type))
|
1314
|
-
else
|
1315
|
-
is_tuple = nil
|
1316
|
-
|
1317
|
-
expand_alias(hint) do |hint|
|
1318
|
-
is_tuple = hint.is_a?(AST::Types::Tuple)
|
1319
|
-
is_tuple &&= node.children.all? {|child| child.type != :splat}
|
1320
|
-
is_tuple &&= node.children.size >= hint.types.size
|
1321
|
-
is_tuple &&= hint.types.map.with_index do |child_type, index|
|
1322
|
-
child_node = node.children[index]
|
1323
|
-
[synthesize(child_node, hint: child_type).type, child_type]
|
1324
|
-
end.all? do |node_type, hint_type|
|
1325
|
-
result = check_relation(sub_type: node_type, super_type: hint_type)
|
1326
|
-
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
|
1327
1337
|
end
|
1328
|
-
end
|
1329
|
-
|
1330
|
-
if is_tuple
|
1331
|
-
array_type = hint
|
1332
1338
|
else
|
1333
|
-
|
1334
|
-
|
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
|
1335
1354
|
end
|
1355
|
+
end
|
1336
1356
|
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
ty.types
|
1345
|
-
else
|
1346
|
-
[ty]
|
1347
|
-
end
|
1348
|
-
end
|
1349
|
-
end.map do |type|
|
1350
|
-
case
|
1351
|
-
when AST::Builtin::Array.instance_type?(type)
|
1352
|
-
type.args.first
|
1353
|
-
when AST::Builtin::Range.instance_type?(type)
|
1354
|
-
type.args.first
|
1355
|
-
else
|
1356
|
-
type
|
1357
|
-
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))
|
1358
1364
|
end
|
1359
|
-
else
|
1360
|
-
[select_super_type(synthesize(e, hint: element_hint).type, element_hint)]
|
1361
1365
|
end
|
1362
1366
|
end
|
1363
|
-
array_type = AST::Builtin::Array.instance_type(AST::Types::Union.build(types: element_types))
|
1364
1367
|
end
|
1365
1368
|
|
1366
|
-
|
1369
|
+
try_array_type(node, nil)
|
1367
1370
|
end
|
1368
1371
|
end
|
1369
1372
|
|
@@ -1672,6 +1675,49 @@ module Steep
|
|
1672
1675
|
when :masgn
|
1673
1676
|
type_masgn(node)
|
1674
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
|
1675
1721
|
when :while, :until
|
1676
1722
|
yield_self do
|
1677
1723
|
cond, body = node.children
|
@@ -1753,9 +1799,15 @@ module Steep
|
|
1753
1799
|
|
1754
1800
|
when :or_asgn, :and_asgn
|
1755
1801
|
yield_self do
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1802
|
+
asgn, rhs = node.children
|
1803
|
+
type, constr = synthesize(rhs, hint: hint)
|
1804
|
+
|
1805
|
+
case asgn.type
|
1806
|
+
when :lvasgn
|
1807
|
+
constr.lvasgn(asgn, type)
|
1808
|
+
when :ivasgn
|
1809
|
+
constr.ivasgn(asgn, type)
|
1810
|
+
end
|
1759
1811
|
end
|
1760
1812
|
|
1761
1813
|
when :defined?
|
@@ -1831,9 +1883,50 @@ module Steep
|
|
1831
1883
|
add_typing node, type: AST::Builtin.any_type
|
1832
1884
|
end
|
1833
1885
|
|
1834
|
-
when :
|
1886
|
+
when :cvasgn
|
1887
|
+
name, rhs = node.children
|
1888
|
+
|
1889
|
+
type, constr = synthesize(rhs, hint: hint)
|
1890
|
+
|
1891
|
+
var_type = if module_context&.class_variables
|
1892
|
+
module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
|
1893
|
+
end
|
1894
|
+
|
1895
|
+
if var_type
|
1896
|
+
result = constr.check_relation(sub_type: type, super_type: var_type)
|
1897
|
+
|
1898
|
+
if result.success?
|
1899
|
+
add_typing node, type: type, constr: constr
|
1900
|
+
else
|
1901
|
+
fallback_to_any node do
|
1902
|
+
Errors::IncompatibleAssignment.new(node: node,
|
1903
|
+
lhs_type: var_type,
|
1904
|
+
rhs_type: type,
|
1905
|
+
result: result)
|
1906
|
+
end
|
1907
|
+
end
|
1908
|
+
else
|
1909
|
+
fallback_to_any(node)
|
1910
|
+
end
|
1911
|
+
|
1912
|
+
when :cvar
|
1913
|
+
name = node.children[0]
|
1914
|
+
var_type = if module_context&.class_variables
|
1915
|
+
module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
|
1916
|
+
end
|
1917
|
+
|
1918
|
+
if var_type
|
1919
|
+
add_typing node, type: var_type
|
1920
|
+
else
|
1921
|
+
fallback_to_any node
|
1922
|
+
end
|
1923
|
+
|
1924
|
+
when :alias
|
1925
|
+
add_typing node, type: AST::Builtin.nil_type
|
1926
|
+
|
1927
|
+
when :splat
|
1835
1928
|
yield_self do
|
1836
|
-
Steep.logger.
|
1929
|
+
Steep.logger.warn { "Unsupported node #{node.type} (#{node.location.expression.source_buffer.name}:#{node.location.expression.line})" }
|
1837
1930
|
|
1838
1931
|
each_child_node node do |child|
|
1839
1932
|
synthesize(child)
|
@@ -1883,136 +1976,202 @@ module Steep
|
|
1883
1976
|
add_typing(node, type: ivar_type)
|
1884
1977
|
end
|
1885
1978
|
|
1979
|
+
def masgn_lhs?(lhs)
|
1980
|
+
lhs.children.all? do |a|
|
1981
|
+
asgn_type = if a.type == :splat
|
1982
|
+
a.children[0].type
|
1983
|
+
else
|
1984
|
+
a.type
|
1985
|
+
end
|
1986
|
+
asgn_type == :lvasgn || asgn_type == :ivasgn
|
1987
|
+
end
|
1988
|
+
end
|
1989
|
+
|
1990
|
+
def lvasgn(node, type)
|
1991
|
+
name = node.children[0].name
|
1992
|
+
env = context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
|
1993
|
+
typing.add_error(
|
1994
|
+
Errors::IncompatibleAssignment.new(node: node,
|
1995
|
+
lhs_type: declared_type,
|
1996
|
+
rhs_type: type,
|
1997
|
+
result: result)
|
1998
|
+
)
|
1999
|
+
end
|
2000
|
+
|
2001
|
+
add_typing(node, type: type, constr: with_updated_context(lvar_env: env))
|
2002
|
+
end
|
2003
|
+
|
2004
|
+
def ivasgn(node, type)
|
2005
|
+
ivar = node.children[0]
|
2006
|
+
|
2007
|
+
type_env.assign(ivar: ivar, type: type, self_type: self_type) do |error|
|
2008
|
+
case error
|
2009
|
+
when Subtyping::Result::Failure
|
2010
|
+
var_type = type_env.get(ivar: ivar)
|
2011
|
+
typing.add_error(Errors::IncompatibleAssignment.new(node: node,
|
2012
|
+
lhs_type: var_type,
|
2013
|
+
rhs_type: type,
|
2014
|
+
result: error))
|
2015
|
+
when nil
|
2016
|
+
fallback_to_any node
|
2017
|
+
end
|
2018
|
+
end
|
2019
|
+
|
2020
|
+
add_typing(node, type: type)
|
2021
|
+
end
|
2022
|
+
|
1886
2023
|
def type_masgn(node)
|
1887
2024
|
lhs, rhs = node.children
|
1888
2025
|
rhs_pair = synthesize(rhs)
|
1889
|
-
rhs_type =
|
2026
|
+
rhs_type = deep_expand_alias(rhs_pair.type)
|
1890
2027
|
|
1891
2028
|
constr = rhs_pair.constr
|
1892
2029
|
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1896
|
-
|
2030
|
+
unless masgn_lhs?(lhs)
|
2031
|
+
Steep.logger.error("Unsupported masgn lhs node: only lvasgn, ivasgn, and splat are supported")
|
2032
|
+
_, constr = constr.fallback_to_any(lhs)
|
2033
|
+
return add_typing(node, type: rhs_type, constr: constr)
|
2034
|
+
end
|
1897
2035
|
|
1898
|
-
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
2036
|
+
falseys, truthys = partition_flatten_types(rhs_type) do |type|
|
2037
|
+
type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
|
2038
|
+
end
|
2039
|
+
|
2040
|
+
unwrap_rhs_type = AST::Types::Union.build(types: truthys)
|
2041
|
+
|
2042
|
+
case
|
2043
|
+
when unwrap_rhs_type.is_a?(AST::Types::Tuple) || (rhs.type == :array && rhs.children.none? {|n| n.type == :splat })
|
2044
|
+
tuple_types = if unwrap_rhs_type.is_a?(AST::Types::Tuple)
|
2045
|
+
unwrap_rhs_type.types.dup
|
2046
|
+
else
|
2047
|
+
rhs.children.map do |node|
|
2048
|
+
typing.type_of(node: node)
|
2049
|
+
end
|
2050
|
+
end
|
2051
|
+
|
2052
|
+
assignment_nodes = lhs.children.dup
|
2053
|
+
leading_assignments = []
|
2054
|
+
trailing_assignments = []
|
2055
|
+
|
2056
|
+
until assignment_nodes.empty?
|
2057
|
+
cursor = assignment_nodes.first
|
2058
|
+
|
2059
|
+
if cursor.type == :splat
|
2060
|
+
break
|
2061
|
+
else
|
2062
|
+
leading_assignments << assignment_nodes.shift
|
1918
2063
|
end
|
2064
|
+
end
|
1919
2065
|
|
1920
|
-
|
2066
|
+
until assignment_nodes.empty?
|
2067
|
+
cursor = assignment_nodes.last
|
1921
2068
|
|
1922
|
-
|
1923
|
-
|
2069
|
+
if cursor.type == :splat
|
2070
|
+
break
|
2071
|
+
else
|
2072
|
+
trailing_assignments.unshift assignment_nodes.pop
|
2073
|
+
end
|
2074
|
+
end
|
1924
2075
|
|
1925
|
-
|
1926
|
-
|
2076
|
+
leading_assignments.each do |asgn|
|
2077
|
+
type = tuple_types.first
|
1927
2078
|
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
Errors::IncompatibleAssignment.new(node: lhs,
|
1934
|
-
lhs_type: declared_type,
|
1935
|
-
rhs_type: type,
|
1936
|
-
result: result)
|
1937
|
-
)
|
1938
|
-
end
|
1939
|
-
add_typing(lhs,
|
1940
|
-
type: ty,
|
1941
|
-
constr: ctr.with_updated_context(lvar_env: env)).constr
|
1942
|
-
when :ivasgn
|
1943
|
-
ivar = lhs.children[0]
|
2079
|
+
if type
|
2080
|
+
tuple_types.shift
|
2081
|
+
else
|
2082
|
+
type = AST::Builtin.nil_type
|
2083
|
+
end
|
1944
2084
|
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
|
1951
|
-
|
1952
|
-
result: error))
|
1953
|
-
when nil
|
1954
|
-
fallback_to_any node
|
1955
|
-
end
|
1956
|
-
end
|
2085
|
+
case asgn.type
|
2086
|
+
when :lvasgn
|
2087
|
+
_, constr = constr.lvasgn(asgn, type)
|
2088
|
+
when :ivasgn
|
2089
|
+
_, constr = constr.ivasgn(asgn, type)
|
2090
|
+
end
|
2091
|
+
end
|
1957
2092
|
|
1958
|
-
|
1959
|
-
|
2093
|
+
trailing_assignments.reverse_each do |asgn|
|
2094
|
+
type = tuple_types.last
|
2095
|
+
|
2096
|
+
if type
|
2097
|
+
tuple_types.pop
|
2098
|
+
else
|
2099
|
+
type = AST::Builtin.nil_type
|
1960
2100
|
end
|
1961
2101
|
|
1962
|
-
|
2102
|
+
case asgn.type
|
2103
|
+
when :lvasgn
|
2104
|
+
_, constr = constr.lvasgn(asgn, type)
|
2105
|
+
when :ivasgn
|
2106
|
+
_, constr = constr.ivasgn(asgn, type)
|
2107
|
+
end
|
2108
|
+
end
|
1963
2109
|
|
1964
|
-
|
1965
|
-
|
2110
|
+
element_type = if tuple_types.empty?
|
2111
|
+
AST::Builtin.nil_type
|
2112
|
+
else
|
2113
|
+
AST::Types::Union.build(types: tuple_types)
|
2114
|
+
end
|
2115
|
+
array_type = AST::Builtin::Array.instance_type(element_type)
|
1966
2116
|
|
1967
|
-
|
1968
|
-
|
2117
|
+
assignment_nodes.each do |asgn|
|
2118
|
+
case asgn.type
|
2119
|
+
when :splat
|
2120
|
+
case asgn.children[0].type
|
1969
2121
|
when :lvasgn
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
2122
|
+
_, constr = constr.lvasgn(asgn.children[0], array_type)
|
2123
|
+
when :ivasgn
|
2124
|
+
_, constr = constr.ivasgn(asgn.children[0], array_type)
|
2125
|
+
end
|
2126
|
+
when :lvasgn
|
2127
|
+
_, constr = constr.lvasgn(asgn, element_type)
|
2128
|
+
when :ivasgn
|
2129
|
+
_,constr = constr.ivasgn(asgn, element_type)
|
2130
|
+
end
|
2131
|
+
end
|
1979
2132
|
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
2133
|
+
unless falseys.empty?
|
2134
|
+
constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
|
2135
|
+
end
|
1983
2136
|
|
1984
|
-
|
1985
|
-
ivar = assignment.children[0]
|
2137
|
+
add_typing(node, type: rhs_type, constr: constr)
|
1986
2138
|
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
when nil
|
1996
|
-
fallback_to_any node
|
1997
|
-
end
|
1998
|
-
end
|
2139
|
+
when flatten_union(unwrap_rhs_type).all? {|type| AST::Builtin::Array.instance_type?(type) }
|
2140
|
+
array_elements = flatten_union(unwrap_rhs_type).map {|type| type.args[0] }
|
2141
|
+
element_type = AST::Types::Union.build(types: array_elements + [AST::Builtin.nil_type])
|
2142
|
+
|
2143
|
+
constr = lhs.children.inject(constr) do |constr, assignment|
|
2144
|
+
case assignment.type
|
2145
|
+
when :lvasgn
|
2146
|
+
_, constr = constr.lvasgn(assignment, element_type)
|
1999
2147
|
|
2000
|
-
|
2148
|
+
when :ivasgn
|
2149
|
+
_, constr = constr.ivasgn(assignment, element_type)
|
2150
|
+
when :splat
|
2151
|
+
case assignment.children[0].type
|
2152
|
+
when :lvasgn
|
2153
|
+
_, constr = constr.lvasgn(assignment.children[0], unwrap_rhs_type)
|
2154
|
+
when :ivasgn
|
2155
|
+
_, constr = constr.ivasgn(assignment.children[0], unwrap_rhs_type)
|
2156
|
+
else
|
2157
|
+
raise
|
2001
2158
|
end
|
2002
2159
|
end
|
2003
2160
|
|
2004
|
-
|
2005
|
-
|
2006
|
-
when rhs_type.is_a?(AST::Types::Any)
|
2007
|
-
fallback_to_any(node)
|
2161
|
+
constr
|
2162
|
+
end
|
2008
2163
|
|
2009
|
-
|
2010
|
-
|
2011
|
-
fallback_to_any(node)
|
2164
|
+
unless falseys.empty?
|
2165
|
+
constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
|
2012
2166
|
end
|
2167
|
+
|
2168
|
+
add_typing(node, type: rhs_type, constr: constr)
|
2013
2169
|
else
|
2014
|
-
|
2015
|
-
|
2170
|
+
unless rhs_type.is_a?(AST::Types::Any)
|
2171
|
+
Steep.logger.error("Unsupported masgn rhs type: array or tuple is supported (#{rhs_type})")
|
2172
|
+
end
|
2173
|
+
_, constr = constr.fallback_to_any(lhs)
|
2174
|
+
add_typing(node, type: rhs_type, constr: constr)
|
2016
2175
|
end
|
2017
2176
|
end
|
2018
2177
|
|
@@ -2063,7 +2222,7 @@ module Steep
|
|
2063
2222
|
else
|
2064
2223
|
case expanded_receiver_type = expand_self(receiver_type)
|
2065
2224
|
when AST::Types::Self
|
2066
|
-
Steep.logger.
|
2225
|
+
Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
|
2067
2226
|
fallback_to_any node do
|
2068
2227
|
Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2069
2228
|
end
|
@@ -3006,7 +3165,12 @@ module Steep
|
|
3006
3165
|
|
3007
3166
|
ty = case type
|
3008
3167
|
when AST::Types::Name::Alias
|
3009
|
-
deep_expand_alias(expand_alias(type), recursive: recursive
|
3168
|
+
deep_expand_alias(expand_alias(type), recursive: recursive.union([type]))
|
3169
|
+
when AST::Types::Union
|
3170
|
+
AST::Types::Union.build(
|
3171
|
+
types: type.types.map {|ty| deep_expand_alias(ty, recursive: recursive, &block) },
|
3172
|
+
location: type.location
|
3173
|
+
)
|
3010
3174
|
else
|
3011
3175
|
type
|
3012
3176
|
end
|
@@ -3018,6 +3182,37 @@ module Steep
|
|
3018
3182
|
end
|
3019
3183
|
end
|
3020
3184
|
|
3185
|
+
def flatten_union(type, acc = [])
|
3186
|
+
case type
|
3187
|
+
when AST::Types::Union
|
3188
|
+
type.types.each {|ty| flatten_union(ty, acc) }
|
3189
|
+
else
|
3190
|
+
acc << type
|
3191
|
+
end
|
3192
|
+
|
3193
|
+
acc
|
3194
|
+
end
|
3195
|
+
|
3196
|
+
def select_flatten_types(type, &block)
|
3197
|
+
types = flatten_union(deep_expand_alias(type))
|
3198
|
+
types.select(&block)
|
3199
|
+
end
|
3200
|
+
|
3201
|
+
def partition_flatten_types(type, &block)
|
3202
|
+
types = flatten_union(deep_expand_alias(type))
|
3203
|
+
types.partition(&block)
|
3204
|
+
end
|
3205
|
+
|
3206
|
+
def flatten_array_elements(type)
|
3207
|
+
flatten_union(deep_expand_alias(type)).flat_map do |type|
|
3208
|
+
if AST::Builtin::Array.instance_type?(type)
|
3209
|
+
type.args
|
3210
|
+
else
|
3211
|
+
[type]
|
3212
|
+
end
|
3213
|
+
end
|
3214
|
+
end
|
3215
|
+
|
3021
3216
|
def expand_alias(type, &block)
|
3022
3217
|
checker.factory.expand_alias(type, &block)
|
3023
3218
|
end
|
@@ -3065,6 +3260,47 @@ module Steep
|
|
3065
3260
|
AST::Types::Name::Instance.new(name: type.name, args: args)
|
3066
3261
|
end
|
3067
3262
|
|
3263
|
+
def try_tuple_type(node, hint)
|
3264
|
+
if node.children.size != hint.types.size
|
3265
|
+
return
|
3266
|
+
end
|
3267
|
+
|
3268
|
+
constr = self
|
3269
|
+
element_types = []
|
3270
|
+
|
3271
|
+
each_child_node(node).with_index do |child, index|
|
3272
|
+
type, constr = constr.synthesize(child, hint: hint.types[index])
|
3273
|
+
element_types << type
|
3274
|
+
end
|
3275
|
+
|
3276
|
+
constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
|
3277
|
+
end
|
3278
|
+
|
3279
|
+
def try_array_type(node, hint)
|
3280
|
+
element_hint = hint ? hint.args[0] : nil
|
3281
|
+
|
3282
|
+
constr = self
|
3283
|
+
element_types = []
|
3284
|
+
|
3285
|
+
each_child_node(node) do |child|
|
3286
|
+
case child.type
|
3287
|
+
when :splat
|
3288
|
+
type, constr = constr.synthesize(child.children[0], hint: hint)
|
3289
|
+
if AST::Builtin::Array.instance_type?(type)
|
3290
|
+
element_types << type.args[0]
|
3291
|
+
else
|
3292
|
+
element_types.push(*flatten_array_elements(type))
|
3293
|
+
end
|
3294
|
+
else
|
3295
|
+
type, constr = constr.synthesize(child, hint: element_hint)
|
3296
|
+
element_types << type
|
3297
|
+
end
|
3298
|
+
end
|
3299
|
+
|
3300
|
+
element_type = AST::Types::Union.build(types: element_types)
|
3301
|
+
constr.add_typing(node, type: AST::Builtin::Array.instance_type(element_type))
|
3302
|
+
end
|
3303
|
+
|
3068
3304
|
def try_hash_type(node, hint)
|
3069
3305
|
case hint
|
3070
3306
|
when AST::Types::Record
|
@@ -26,7 +26,7 @@ module Steep
|
|
26
26
|
factory.type(constant.type)
|
27
27
|
end
|
28
28
|
rescue => exn
|
29
|
-
Steep.logger.
|
29
|
+
Steep.logger.debug "Looking up a constant failed: name=#{name}, context=[#{context.join(", ")}], error=#{exn.inspect}"
|
30
30
|
nil
|
31
31
|
end
|
32
32
|
end
|
@@ -70,6 +70,14 @@ module Steep
|
|
70
70
|
def const_context
|
71
71
|
const_env.context
|
72
72
|
end
|
73
|
+
|
74
|
+
def class_variables
|
75
|
+
if module_definition
|
76
|
+
@class_variables ||= module_definition.class_variables.transform_values do |var_def|
|
77
|
+
var_def.type
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
73
81
|
end
|
74
82
|
|
75
83
|
attr_reader :method_context
|
@@ -35,12 +35,13 @@ module Steep
|
|
35
35
|
|
36
36
|
def insert_context(range, context:, entry: self.root)
|
37
37
|
entry.sub_entries.each do |sub|
|
38
|
-
next if sub.range.begin
|
39
|
-
next if range.begin
|
38
|
+
next if sub.range.begin <= range.begin && range.end <= sub.range.end
|
39
|
+
next if range.begin <= sub.range.begin && sub.range.end <= range.end
|
40
40
|
next if range.end <= sub.range.begin
|
41
41
|
next if sub.range.end <= range.begin
|
42
42
|
|
43
|
-
|
43
|
+
Steep.logger.error { "Range crossing: sub range=#{sub.range}, new range=#{range}" }
|
44
|
+
raise
|
44
45
|
end
|
45
46
|
|
46
47
|
sup = entry.sub_entries.find do |sub|
|
@@ -47,6 +47,37 @@ module Steep
|
|
47
47
|
f.merge([node])
|
48
48
|
]
|
49
49
|
|
50
|
+
when :masgn
|
51
|
+
lhs, rhs = node.children
|
52
|
+
|
53
|
+
lt, lf = nodes(node: lhs)
|
54
|
+
rt, rf = nodes(node: rhs)
|
55
|
+
|
56
|
+
[
|
57
|
+
(lt + rt).merge([node]),
|
58
|
+
(lf + rf).merge([node])
|
59
|
+
]
|
60
|
+
|
61
|
+
when :mlhs
|
62
|
+
nodes = [node]
|
63
|
+
|
64
|
+
node.children.each do |child|
|
65
|
+
case child.type
|
66
|
+
when :lvasgn
|
67
|
+
nodes << child
|
68
|
+
when :splat
|
69
|
+
if node.children[0].type == :lvasgn
|
70
|
+
nodes << child
|
71
|
+
nodes << child.children[0]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
[
|
77
|
+
Result.new(nodes),
|
78
|
+
Result.new(nodes)
|
79
|
+
]
|
80
|
+
|
50
81
|
when :and
|
51
82
|
lhs, rhs = node.children
|
52
83
|
|
data/lib/steep/typing.rb
CHANGED
@@ -126,6 +126,13 @@ module Steep
|
|
126
126
|
end_pos = node.loc.end.begin_pos
|
127
127
|
add_context(begin_pos..end_pos, context: context)
|
128
128
|
|
129
|
+
when :for
|
130
|
+
_, collection, _ = node.children
|
131
|
+
|
132
|
+
begin_pos = collection.loc.expression.end_pos
|
133
|
+
end_pos = node.loc.end.begin_pos
|
134
|
+
|
135
|
+
add_context(begin_pos..end_pos, context: context)
|
129
136
|
else
|
130
137
|
raise "Unexpected node for insert_context: #{node.type}"
|
131
138
|
end
|
data/lib/steep/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|