steep 0.35.0 → 0.36.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ddd53798b724f6fd1a93d869b03a3864db04bed448552a75dadeabe8d1bc51e
4
- data.tar.gz: c85f6c58a010ed11dfc1041f8ba98007e0f557d7bda133222b94915dfed0d6ca
3
+ metadata.gz: 5203340eb3b3534da5f1071cc497bbe7a481553e909088277c83dbfe5e5c0bbc
4
+ data.tar.gz: 11863c0ea9b692de6fba552ec01645525240c025c598235f9b3bf88e35571ed5
5
5
  SHA512:
6
- metadata.gz: 79a7742bdef0d368aa2dceaa528cf3e4bc74bccefafc0d6c366aa94994917e7d5560c8d4fd6f03adf0d50c3b8536d80d7e998bba3a9dc5cb872c7047c0079cba
7
- data.tar.gz: 512b5bdf6efd6e465d5e3147de2df6cafb549fe68e05890efc13fffcc763b0cec1c48005a1734b6ade2cd120fa48059c435c20bad4b9998b1d15a0b4f557f615
6
+ metadata.gz: 9897fecb7ca5b60da9eeb236e5f06af1a9b2fa2a2df2bd87d07f7a496f0f05b988b30db2e294797304c6d7f0e8fe478cdc1d41049cbaf2e56c45108444b2c721
7
+ data.tar.gz: fa2dca2cd37d74e39878ab3da7a5453a714f50e921fcd1c0e75054bf083a11003cb5799f4f92531a10bce6074dce3cce88c90daeb214b9fb45d7f5612e294fb3
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.36.0 (2020-11-16)
6
+
7
+ * Flow-sensitive typing improvements with `||` and `&&` ([#260](https://github.com/soutaro/steep/pull/260))
8
+ * Type-case improvement ([#259](https://github.com/soutaro/steep/pull/259))
9
+ * Subtyping between `bool` and logic types ([#258](https://github.com/soutaro/steep/pull/258))
10
+
5
11
  ## 0.35.0 (2020-11-14)
6
12
 
7
13
  * Support third party RBS repository ([#231](https://github.com/soutaro/steep/pull/231), [#254](https://github.com/soutaro/steep/pull/254), [#255](https://github.com/soutaro/steep/pull/255))
@@ -18,7 +18,7 @@ module Steep
18
18
  end
19
19
 
20
20
  def ==(other)
21
- other.class ==self.class
21
+ other.class == self.class
22
22
  end
23
23
 
24
24
  alias eql? ==
@@ -57,6 +57,25 @@ module Steep
57
57
  @location = location
58
58
  end
59
59
  end
60
+
61
+ class Env < Base
62
+ attr_reader :truthy, :falsy
63
+
64
+ def initialize(truthy:, falsy:, location: nil)
65
+ @truthy = truthy
66
+ @falsy = falsy
67
+ end
68
+
69
+ def ==(other)
70
+ other.is_a?(Env) && other.truthy == truthy && other.falsy == falsy
71
+ end
72
+
73
+ alias eql? ==
74
+
75
+ def hash
76
+ self.class.hash ^ truthy.hash ^ falsy.hash
77
+ end
78
+ end
60
79
  end
61
80
  end
62
81
  end
@@ -127,6 +127,24 @@ module Steep
127
127
  Result::Failure.new(error: error, trace: trace)
128
128
  end
129
129
 
130
+ def true_type?(type)
131
+ case type
132
+ when AST::Types::Literal
133
+ type.value == true
134
+ else
135
+ AST::Builtin::TrueClass.instance_type?(type)
136
+ end
137
+ end
138
+
139
+ def false_type?(type)
140
+ case type
141
+ when AST::Types::Literal
142
+ type.value == false
143
+ else
144
+ AST::Builtin::FalseClass.instance_type?(type)
145
+ end
146
+ end
147
+
130
148
  def check0(relation, self_type:, assumption:, trace:, constraints:)
131
149
  # puts relation
132
150
  trace.type(relation.sub_type, relation.super_type) do
@@ -146,6 +164,9 @@ module Steep
146
164
  when relation.sub_type.is_a?(AST::Types::Bot)
147
165
  success(constraints: constraints)
148
166
 
167
+ when relation.sub_type.is_a?(AST::Types::Logic::Base) && (true_type?(relation.super_type) || false_type?(relation.super_type))
168
+ success(constraints: constraints)
169
+
149
170
  when relation.super_type.is_a?(AST::Types::Boolean)
150
171
  check(
151
172
  Relation.new(sub_type: relation.sub_type, super_type: AST::Types::Union.build(types: [AST::Builtin.true_type, AST::Builtin.false_type])),
@@ -1476,7 +1476,18 @@ module Steep
1476
1476
  .for_branch(right)
1477
1477
  .synthesize(right)
1478
1478
 
1479
- type = if left_type.is_a?(AST::Types::Boolean)
1479
+ truthy_env, _ = interpreter.eval(env: truthy_env, type: right_type, node: right)
1480
+
1481
+ env = if right_type.is_a?(AST::Types::Bot)
1482
+ falsey_env
1483
+ else
1484
+ context.lvar_env.join(falsey_env, constr.context.lvar_env)
1485
+ end
1486
+
1487
+ type = case
1488
+ when left_type.is_a?(AST::Types::Logic::Base) && right_type.is_a?(AST::Types::Logic::Base)
1489
+ AST::Types::Logic::Env.new(truthy: truthy_env, falsy: env)
1490
+ when check_relation(sub_type: left_type, super_type: AST::Types::Boolean.new).success?
1480
1491
  union_type(left_type, right_type)
1481
1492
  else
1482
1493
  union_type(right_type, AST::Builtin.nil_type)
@@ -1484,13 +1495,7 @@ module Steep
1484
1495
 
1485
1496
  add_typing(node,
1486
1497
  type: type,
1487
- constr: constr.update_lvar_env do
1488
- if right_type.is_a?(AST::Types::Bot)
1489
- falsey_env
1490
- else
1491
- context.lvar_env.join(falsey_env, constr.context.lvar_env)
1492
- end
1493
- end)
1498
+ constr: constr.update_lvar_env { env })
1494
1499
  end
1495
1500
 
1496
1501
  when :or
@@ -1502,24 +1507,31 @@ module Steep
1502
1507
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1503
1508
  truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: left_type, node: left)
1504
1509
 
1505
- left_type_t, _ = checker.factory.unwrap_optional(left_type)
1510
+ left_type, _ = checker.factory.unwrap_optional(left_type)
1506
1511
  right_type, constr = constr
1507
1512
  .update_lvar_env { falsey_env }
1508
1513
  .tap {|constr| typing.add_context_for_node(right, context: constr.context) }
1509
1514
  .for_branch(right)
1510
- .synthesize(right, hint: left_type_t)
1515
+ .synthesize(right, hint: left_type)
1511
1516
 
1512
- type = union_type(left_type_t, right_type)
1517
+ _, falsey_env = interpreter.eval(env: falsey_env, type: right_type, node: right)
1518
+
1519
+ env = if right_type.is_a?(AST::Types::Bot)
1520
+ truthy_env
1521
+ else
1522
+ context.lvar_env.join(truthy_env, constr.context.lvar_env)
1523
+ end
1524
+
1525
+ type = case
1526
+ when left_type.is_a?(AST::Types::Logic::Base) && right_type.is_a?(AST::Types::Logic::Base)
1527
+ AST::Types::Logic::Env.new(truthy: env, falsy: falsey_env)
1528
+ else
1529
+ union_type(left_type, right_type)
1530
+ end
1513
1531
 
1514
1532
  add_typing(node,
1515
1533
  type: type,
1516
- constr: constr.update_lvar_env do
1517
- if right_type.is_a?(AST::Types::Bot)
1518
- truthy_env
1519
- else
1520
- context.lvar_env.join(truthy_env, constr.context.lvar_env)
1521
- end
1522
- end)
1534
+ constr: constr.update_lvar_env { env })
1523
1535
  end
1524
1536
 
1525
1537
  when :if
@@ -1584,6 +1596,18 @@ module Steep
1584
1596
 
1585
1597
  cond_type, constr = constr.synthesize(cond)
1586
1598
  _, cond_vars = interpreter.decompose_value(cond)
1599
+ unless cond_vars.empty?
1600
+ first_var = cond_vars.to_a[0]
1601
+ var_node = cond.updated(
1602
+ :lvar,
1603
+ [
1604
+ ASTUtils::Labeling::LabeledName.new(name: first_var, label: 0)
1605
+ ]
1606
+ )
1607
+ else
1608
+ first_var = nil
1609
+ var_node = cond
1610
+ end
1587
1611
 
1588
1612
  when_constr = constr
1589
1613
  whens.each do |clause|
@@ -1593,9 +1617,15 @@ module Steep
1593
1617
  test_envs = []
1594
1618
 
1595
1619
  tests.each do |test|
1596
- test_node = test.updated(:send, [test, :===, cond.dup])
1620
+ test_node = test.updated(:send, [test, :===, var_node])
1597
1621
  test_type, test_constr = test_constr.synthesize(test_node)
1598
1622
  truthy_env, falsy_env = interpreter.eval(type: test_type, node: test_node, env: test_constr.context.lvar_env)
1623
+ truthy_env = cond_vars.inject(truthy_env) do |env, var|
1624
+ env.assign!(var, node: test_node, type: env[first_var])
1625
+ end
1626
+ falsy_env = cond_vars.inject(falsy_env) do |env, var|
1627
+ env.assign!(var, node: test_node, type: env[first_var])
1628
+ end
1599
1629
  test_envs << truthy_env
1600
1630
  test_constr = test_constr.update_lvar_env { falsy_env }
1601
1631
  end
@@ -1625,10 +1655,6 @@ module Steep
1625
1655
  types = branch_pairs.map(&:type)
1626
1656
  constrs = branch_pairs.map(&:constr)
1627
1657
 
1628
- unless els
1629
- constrs << when_constr
1630
- end
1631
-
1632
1658
  if when_constr.context.lvar_env[cond_vars.first].is_a?(AST::Types::Bot)
1633
1659
  # Exhaustive
1634
1660
  if els
@@ -1636,6 +1662,7 @@ module Steep
1636
1662
  end
1637
1663
  else
1638
1664
  unless els
1665
+ constrs << when_constr
1639
1666
  types << AST::Builtin.nil_type
1640
1667
  end
1641
1668
  end
@@ -46,6 +46,9 @@ module Steep
46
46
  end
47
47
 
48
48
  case type
49
+ when AST::Types::Logic::Env
50
+ truthy_env = type.truthy
51
+ falsy_env = type.falsy
49
52
  when AST::Types::Logic::ReceiverIsNil
50
53
  case value_node.type
51
54
  when :send
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.35.0"
2
+ VERSION = "0.36.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.35.0
4
+ version: 0.36.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-11-14 00:00:00.000000000 Z
11
+ date: 2020-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser