steep 0.20.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.
@@ -638,7 +638,8 @@ module Steep
638
638
  when :__skip__
639
639
  add_typing(node, type: AST::Builtin.any_type)
640
640
  else
641
- rhs_result = synthesize(rhs, hint: hint || context.lvar_env.declared_types[name]&.type)
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
- unless type
1019
+
1020
+ if type
1021
+ add_typing(node, type: type)
1022
+ else
1002
1023
  type = AST::Builtin.any_type
1003
- 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)
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
- Steep.logger.error { "Unknown variable: #{node}" }
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
- Steep.logger.error { "Unknown variable: #{node}" }
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 = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
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 = expand_alias(hint) {|hint| test_literal_type(node.children[0], hint) }
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 = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_)}
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
- add_typing(node, type: AST::Types::Boolean.new)
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
- typing.add_error Errors::FallbackAny.new(node: node) unless hint
1298
-
1299
- array_type = if hint
1300
- if check_relation(sub_type: AST::Builtin::Array.instance_type(AST::Builtin.any_type),
1301
- super_type: hint).success?
1302
- hint
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
- element_hint = expand_alias(hint) do |hint|
1327
- 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
1328
1354
  end
1355
+ end
1329
1356
 
1330
- element_types = node.children.flat_map do |e|
1331
- if e.type == :splat
1332
- Steep.logger.info "Typing of splat in array is incompatible with Ruby; it does not use #to_a method"
1333
- synthesize(e.children.first).type.yield_self do |type|
1334
- expand_alias(type) do |ty|
1335
- case ty
1336
- when AST::Types::Union
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
- add_typing(node, type: array_type)
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,15 @@ module Steep
1746
1799
 
1747
1800
  when :or_asgn, :and_asgn
1748
1801
  yield_self do
1749
- _, rhs = node.children
1750
- rhs_type = synthesize(rhs).type
1751
- 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
1752
1811
  end
1753
1812
 
1754
1813
  when :defined?
@@ -1824,9 +1883,50 @@ module Steep
1824
1883
  add_typing node, type: AST::Builtin.any_type
1825
1884
  end
1826
1885
 
1827
- 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
1828
1928
  yield_self do
1829
- 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})" }
1830
1930
 
1831
1931
  each_child_node node do |child|
1832
1932
  synthesize(child)
@@ -1876,136 +1976,202 @@ module Steep
1876
1976
  add_typing(node, type: ivar_type)
1877
1977
  end
1878
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
+
1879
2023
  def type_masgn(node)
1880
2024
  lhs, rhs = node.children
1881
2025
  rhs_pair = synthesize(rhs)
1882
- rhs_type = expand_alias(rhs_pair.type)
2026
+ rhs_type = deep_expand_alias(rhs_pair.type)
1883
2027
 
1884
2028
  constr = rhs_pair.constr
1885
2029
 
1886
- if lhs.children.all? {|a| a.type == :lvasgn || a.type == :ivasgn}
1887
- case
1888
- when rhs.type == :array && lhs.children.size == rhs.children.size
1889
- # 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
1890
2035
 
1891
- constr = lhs.children.zip(rhs.children).inject(constr) do |ctr, (lhs, rhs)|
1892
- case lhs.type
1893
- when :lvasgn
1894
- name = lhs.children[0].name
1895
- type = typing.type_of(node: rhs)
1896
- env = ctr.context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
1897
- typing.add_error(
1898
- Errors::IncompatibleAssignment.new(node: lhs,
1899
- lhs_type: declared_type,
1900
- rhs_type: type,
1901
- result: result)
1902
- )
1903
- end
1904
- add_typing(lhs,
1905
- type: type,
1906
- constr: ctr.with_updated_context(lvar_env: env))
1907
- when :ivasgn
1908
- type_ivasgn(lhs.children.first, rhs, lhs)
1909
- constr
1910
- 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
1911
2063
  end
2064
+ end
1912
2065
 
1913
- add_typing(node, type: rhs_type, constr: constr)
2066
+ until assignment_nodes.empty?
2067
+ cursor = assignment_nodes.last
1914
2068
 
1915
- when rhs_type.is_a?(AST::Types::Tuple)
1916
- # a, @b = tuple
2069
+ if cursor.type == :splat
2070
+ break
2071
+ else
2072
+ trailing_assignments.unshift assignment_nodes.pop
2073
+ end
2074
+ end
1917
2075
 
1918
- constr = lhs.children.zip(rhs_type.types).inject(constr) do |ctr, (lhs, type)|
1919
- ty = type || AST::Builtin.nil_type
2076
+ leading_assignments.each do |asgn|
2077
+ type = tuple_types.first
1920
2078
 
1921
- case lhs.type
1922
- when :lvasgn
1923
- name = lhs.children[0].name
1924
- env = ctr.context.lvar_env.assign(name, node: node, type: ty) do |declared_type, type, result|
1925
- typing.add_error(
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]
2079
+ if type
2080
+ tuple_types.shift
2081
+ else
2082
+ type = AST::Builtin.nil_type
2083
+ end
1937
2084
 
1938
- type_env.assign(ivar: ivar, type: ty, self_type: self_type) do |error|
1939
- case error
1940
- when Subtyping::Result::Failure
1941
- ivar_type = type_env.get(ivar: ivar)
1942
- typing.add_error(Errors::IncompatibleAssignment.new(node: lhs,
1943
- lhs_type: ivar_type,
1944
- rhs_type: ty,
1945
- result: error))
1946
- when nil
1947
- fallback_to_any node
1948
- end
1949
- 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
1950
2092
 
1951
- ctr
1952
- 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
1953
2100
  end
1954
2101
 
1955
- 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
1956
2109
 
1957
- when AST::Builtin::Array.instance_type?(rhs_type)
1958
- 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)
1959
2116
 
1960
- constr = lhs.children.inject(constr) do |ctr, assignment|
1961
- case assignment.type
2117
+ assignment_nodes.each do |asgn|
2118
+ case asgn.type
2119
+ when :splat
2120
+ case asgn.children[0].type
1962
2121
  when :lvasgn
1963
- name = assignment.children[0].name
1964
- env = ctr.context.lvar_env.assign(name, node: node, type: element_type) do |declared_type, type, result|
1965
- typing.add_error(
1966
- Errors::IncompatibleAssignment.new(node: assignment,
1967
- lhs_type: declared_type,
1968
- rhs_type: type,
1969
- result: result)
1970
- )
1971
- 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
1972
2132
 
1973
- add_typing(assignment,
1974
- type: element_type,
1975
- 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
1976
2136
 
1977
- when :ivasgn
1978
- ivar = assignment.children[0]
2137
+ add_typing(node, type: rhs_type, constr: constr)
1979
2138
 
1980
- type_env.assign(ivar: ivar, type: element_type, self_type: self_type) do |error|
1981
- case error
1982
- when Subtyping::Result::Failure
1983
- type = type_env.get(ivar: ivar)
1984
- typing.add_error(Errors::IncompatibleAssignment.new(node: assignment,
1985
- lhs_type: type,
1986
- rhs_type: element_type,
1987
- result: error))
1988
- when nil
1989
- fallback_to_any node
1990
- end
1991
- 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])
1992
2142
 
1993
- ctr
2143
+ constr = lhs.children.inject(constr) do |constr, assignment|
2144
+ case assignment.type
2145
+ when :lvasgn
2146
+ _, constr = constr.lvasgn(assignment, element_type)
2147
+
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
1994
2158
  end
1995
2159
  end
1996
2160
 
1997
- add_typing node, type: rhs_type, constr: constr
1998
-
1999
- when rhs_type.is_a?(AST::Types::Any)
2000
- fallback_to_any(node)
2161
+ constr
2162
+ end
2001
2163
 
2002
- else
2003
- Steep.logger.error("Unsupported masgn: #{rhs.type} (#{rhs_type})")
2004
- 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)}
2005
2166
  end
2167
+
2168
+ add_typing(node, type: rhs_type, constr: constr)
2006
2169
  else
2007
- Steep.logger.error("Unsupported masgn left hand side")
2008
- 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)
2009
2175
  end
2010
2176
  end
2011
2177
 
@@ -2056,7 +2222,7 @@ module Steep
2056
2222
  else
2057
2223
  case expanded_receiver_type = expand_self(receiver_type)
2058
2224
  when AST::Types::Self
2059
- Steep.logger.error "`self` type cannot be resolved to concrete type"
2225
+ Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
2060
2226
  fallback_to_any node do
2061
2227
  Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
2062
2228
  end
@@ -2999,7 +3165,12 @@ module Steep
2999
3165
 
3000
3166
  ty = case type
3001
3167
  when AST::Types::Name::Alias
3002
- 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
+ )
3003
3174
  else
3004
3175
  type
3005
3176
  end
@@ -3011,19 +3182,51 @@ module Steep
3011
3182
  end
3012
3183
  end
3013
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
+
3014
3216
  def expand_alias(type, &block)
3015
3217
  checker.factory.expand_alias(type, &block)
3016
3218
  end
3017
3219
 
3018
3220
  def test_literal_type(literal, hint)
3019
- case hint
3020
- when AST::Types::Literal
3021
- if hint.value == literal
3022
- hint
3023
- end
3024
- when AST::Types::Union
3025
- if hint.types.any? {|ty| ty.is_a?(AST::Types::Literal) && ty.value == literal}
3026
- hint
3221
+ if hint
3222
+ case hint
3223
+ when AST::Types::Any
3224
+ nil
3225
+ else
3226
+ literal_type = AST::Types::Literal.new(value: literal, location: nil)
3227
+ if check_relation(sub_type: literal_type, super_type: hint).success?
3228
+ hint
3229
+ end
3027
3230
  end
3028
3231
  end
3029
3232
  end
@@ -3057,6 +3260,47 @@ module Steep
3057
3260
  AST::Types::Name::Instance.new(name: type.name, args: args)
3058
3261
  end
3059
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
+
3060
3304
  def try_hash_type(node, hint)
3061
3305
  case hint
3062
3306
  when AST::Types::Record