steep 0.24.0 → 0.25.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 +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
|