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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3fc0de639f659b9b59f83ca0f8968550e7230ee1dbb6ae8e0d005325267ab46e
4
- data.tar.gz: a1f73b521a222fa1313c2f58b1e0d3fb2a07149aba42c17e91c8df495e3319de
3
+ metadata.gz: c290301da65ed473b092cd6c2ea39eebe02f566124a1fa32e0f420d290513cbf
4
+ data.tar.gz: ca4fca20e9f3f0b19c57b98d6cdfce0023aeeff8cd0fcd2ee0fc91346e5e0816
5
5
  SHA512:
6
- metadata.gz: bcedd630c3b51bc4d3a24549c6bcde88156af410be2b64ec51d813c238f3cb5d5f9f85b980302cae3cacd007e478ae51f99019ed10f3b6a31df84723bd43f35b
7
- data.tar.gz: da09a3c3e7f762ec48b378533b6c624c1b9590a0cfd58ffc7aed87212fde2c67897bc1aa745eaa8f4baeaa19b1e6c7b0a4826e7fb6e582a6ef6798ee3b4a47a4
6
+ metadata.gz: 76c3b0c76e303bcc558bf20efeebe3ddaa3caef432f5d325261261f6d8431f5bbd36bc44af9a4a4dd6a90f2db30ac35ca044181b25063890c0e68c5499d7792c
7
+ data.tar.gz: a5fa8fba718f599806d9d0ad62a66c138261469d41694bb39ebafe1b8736ad255e890c55f0e3b4f180f4e0212f0b65b31b5957b5c337cba42d1129b9e935e577
@@ -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))
@@ -29,7 +29,10 @@ module Steep
29
29
  type
30
30
  end
31
31
  end.compact.uniq.yield_self do |tys|
32
- if tys.length == 1
32
+ case tys.length
33
+ when 0
34
+ AST::Types::Bot.new
35
+ when 1
33
36
  tys.first
34
37
  else
35
38
  new(types: tys.sort_by(&:hash), location: location)
@@ -60,6 +60,10 @@ module Steep
60
60
  Steep.log_error source_file.status.error
61
61
  end
62
62
  end
63
+ when Project::Target::SignatureOtherErrorStatus
64
+ Steep.log_error status.error
65
+ else
66
+ Steep.logger.error { "Unexpected status: #{status.class}" }
63
67
  end
64
68
  end
65
69
  end
@@ -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
- if file.type_check(check, timestamp)
198
- type_check_sources << file
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
 
@@ -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.loc.else
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.is_a?(AST::Types::Name::Base)
322
- tuple_interface = factory.interface(relation.sub_type, private: false)
323
- type_interface = factory.interface(relation.super_type, private: false)
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
- check_interface(tuple_interface,
326
- type_interface,
327
- self_type: self_type,
328
- assumption: assumption,
329
- trace: trace,
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
- unless type
1019
+
1020
+ if type
1021
+ add_typing(node, type: type)
1022
+ else
1003
1023
  type = AST::Builtin.any_type
1004
- Steep.logger.error { "Unknown arg type: #{node}" }
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
- Steep.logger.error { "Unknown variable: #{node}" }
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
- Steep.logger.error { "Unknown variable: #{node}" }
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
- typing.add_error Errors::FallbackAny.new(node: node) unless hint
1305
-
1306
- array_type = if hint
1307
- if check_relation(sub_type: AST::Builtin::Array.instance_type(AST::Builtin.any_type),
1308
- super_type: hint).success?
1309
- hint
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
- element_hint = expand_alias(hint) do |hint|
1334
- AST::Builtin::Array.instance_type?(hint) && hint.args[0]
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
- element_types = node.children.flat_map do |e|
1338
- if e.type == :splat
1339
- Steep.logger.info "Typing of splat in array is incompatible with Ruby; it does not use #to_a method"
1340
- synthesize(e.children.first).type.yield_self do |type|
1341
- expand_alias(type) do |ty|
1342
- case ty
1343
- when AST::Types::Union
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
- add_typing(node, type: array_type)
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
- _, rhs = node.children
1757
- rhs_type = synthesize(rhs).type
1758
- add_typing(node, type: rhs_type)
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 :splat, :sclass, :alias
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.error "Unsupported node #{node.type} (#{node.location.expression.source_buffer.name}:#{node.location.expression.line})"
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 = expand_alias(rhs_pair.type)
2026
+ rhs_type = deep_expand_alias(rhs_pair.type)
1890
2027
 
1891
2028
  constr = rhs_pair.constr
1892
2029
 
1893
- if lhs.children.all? {|a| a.type == :lvasgn || a.type == :ivasgn}
1894
- case
1895
- when rhs.type == :array && lhs.children.size == rhs.children.size
1896
- # a, @b = x, y
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
- constr = lhs.children.zip(rhs.children).inject(constr) do |ctr, (lhs, rhs)|
1899
- case lhs.type
1900
- when :lvasgn
1901
- name = lhs.children[0].name
1902
- type = typing.type_of(node: rhs)
1903
- env = ctr.context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
1904
- typing.add_error(
1905
- Errors::IncompatibleAssignment.new(node: lhs,
1906
- lhs_type: declared_type,
1907
- rhs_type: type,
1908
- result: result)
1909
- )
1910
- end
1911
- add_typing(lhs,
1912
- type: type,
1913
- constr: ctr.with_updated_context(lvar_env: env))
1914
- when :ivasgn
1915
- type_ivasgn(lhs.children.first, rhs, lhs)
1916
- constr
1917
- end
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
- add_typing(node, type: rhs_type, constr: constr)
2066
+ until assignment_nodes.empty?
2067
+ cursor = assignment_nodes.last
1921
2068
 
1922
- when rhs_type.is_a?(AST::Types::Tuple)
1923
- # a, @b = tuple
2069
+ if cursor.type == :splat
2070
+ break
2071
+ else
2072
+ trailing_assignments.unshift assignment_nodes.pop
2073
+ end
2074
+ end
1924
2075
 
1925
- constr = lhs.children.zip(rhs_type.types).inject(constr) do |ctr, (lhs, type)|
1926
- ty = type || AST::Builtin.nil_type
2076
+ leading_assignments.each do |asgn|
2077
+ type = tuple_types.first
1927
2078
 
1928
- case lhs.type
1929
- when :lvasgn
1930
- name = lhs.children[0].name
1931
- env = ctr.context.lvar_env.assign(name, node: node, type: ty) do |declared_type, type, result|
1932
- typing.add_error(
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
- type_env.assign(ivar: ivar, type: ty, self_type: self_type) do |error|
1946
- case error
1947
- when Subtyping::Result::Failure
1948
- ivar_type = type_env.get(ivar: ivar)
1949
- typing.add_error(Errors::IncompatibleAssignment.new(node: lhs,
1950
- lhs_type: ivar_type,
1951
- rhs_type: ty,
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
- ctr
1959
- end
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
- add_typing(node, type: rhs_type, constr: constr)
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
- when AST::Builtin::Array.instance_type?(rhs_type)
1965
- element_type = AST::Types::Union.build(types: [rhs_type.args.first, AST::Builtin.nil_type])
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
- constr = lhs.children.inject(constr) do |ctr, assignment|
1968
- case assignment.type
2117
+ assignment_nodes.each do |asgn|
2118
+ case asgn.type
2119
+ when :splat
2120
+ case asgn.children[0].type
1969
2121
  when :lvasgn
1970
- name = assignment.children[0].name
1971
- env = ctr.context.lvar_env.assign(name, node: node, type: element_type) do |declared_type, type, result|
1972
- typing.add_error(
1973
- Errors::IncompatibleAssignment.new(node: assignment,
1974
- lhs_type: declared_type,
1975
- rhs_type: type,
1976
- result: result)
1977
- )
1978
- end
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
- add_typing(assignment,
1981
- type: element_type,
1982
- constr: ctr.with_updated_context(lvar_env: env)).constr
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
- when :ivasgn
1985
- ivar = assignment.children[0]
2137
+ add_typing(node, type: rhs_type, constr: constr)
1986
2138
 
1987
- type_env.assign(ivar: ivar, type: element_type, self_type: self_type) do |error|
1988
- case error
1989
- when Subtyping::Result::Failure
1990
- type = type_env.get(ivar: ivar)
1991
- typing.add_error(Errors::IncompatibleAssignment.new(node: assignment,
1992
- lhs_type: type,
1993
- rhs_type: element_type,
1994
- result: error))
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
- ctr
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
- add_typing node, type: rhs_type, constr: constr
2005
-
2006
- when rhs_type.is_a?(AST::Types::Any)
2007
- fallback_to_any(node)
2161
+ constr
2162
+ end
2008
2163
 
2009
- else
2010
- Steep.logger.error("Unsupported masgn: #{rhs.type} (#{rhs_type})")
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
- Steep.logger.error("Unsupported masgn left hand side")
2015
- fallback_to_any(node)
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.error "`self` type cannot be resolved to concrete type"
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 << type)
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.error "Looking up a constant failed: name=#{name}, context=[#{context.join(", ")}], error=#{exn.inspect}"
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 < range.begin && range.end <= sub.range.end
39
- next if range.begin < sub.range.begin && sub.range.end <= range.end
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
- raise "Range crossing: sub range=#{sub.range}, new range=#{range}"
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
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.24.0"
2
+ VERSION = "0.25.0"
3
3
  end
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.24.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-10 00:00:00.000000000 Z
11
+ date: 2020-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser