steep 0.35.0 → 0.36.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: 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