steep 1.5.0.pre.3 → 1.5.0.pre.4

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: 1fe028736497aa5746e128c32a325b6b98101dc30a97f82b16d572db9a3d39b8
4
- data.tar.gz: 1ac7376836e97b860052b75aab42a08ad7a06143d8e0208c9fc764ea54e74cee
3
+ metadata.gz: cfb1de89ec50042cf06306ab17717671e8b6a8451ea2885b4af8085226f7994e
4
+ data.tar.gz: 1b67eb25821061afe42c8c4dd644b30370e866ac9ef8066cb77031799c981145
5
5
  SHA512:
6
- metadata.gz: 9e1dbff5baebfd9ffd88390dcff4831d7d2bead258bd860fa7a6cf62e4c7880c398788c1d6f3ad163ac4256bcf9f25e59f78350a0422e4afa6ee360d38dbc876
7
- data.tar.gz: ba0a4d84cb3a50c764369766fceae755fd6ec5717a488904db5d29f5b2ad48d05dadcec6ce37ef9092616aa540e3c513eaa526983ed15fe3096349d685aa0f24
6
+ metadata.gz: 1f0b3400822be747c45ed1d5c2cdfbddf8c0fdf70963061b66308464a18a95e493cc94ad406bbc444f618f562e0f95f276600c27e3ec2269f01504727b0528c7
7
+ data.tar.gz: 45b2a32802ea5ab504a8c3ee04f714a87b27227ffa66282d64243e3161aa0628001f1925e3ad7aaf09fcd0fbddc4def36e9b9940c76a87b195c2f51b19006bf9
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.5.0.pre.4 (2023-07-06)
6
+
7
+ ### Type checker core
8
+
9
+ * Fix unreachability test ([#842](https://github.com/soutaro/steep/pull/842))
10
+ * Make type of `case` node `untyped` rather than `nil` ([#841](https://github.com/soutaro/steep/pull/841))
11
+ * Fix `#partition_union` ([#840](https://github.com/soutaro/steep/pull/840))
12
+ * Fix type-case ([#839](https://github.com/soutaro/steep/pull/839))
13
+
5
14
  ## 1.5.0.pre.3 (2023-07-05)
6
15
 
7
16
  ### Type checker core
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (1.5.0.pre.3)
4
+ steep (1.5.0.pre.4)
5
5
  activesupport (>= 5.1)
6
6
  concurrent-ruby (>= 1.1.10)
7
7
  csv (>= 3.0.9)
@@ -358,16 +358,21 @@ module Steep
358
358
  partition_union(unfold)
359
359
  end
360
360
  when AST::Types::Union
361
- falsy_types, truthy_types = type.types.partition do |type|
362
- (type.is_a?(AST::Types::Literal) && type.value == false) ||
363
- type.is_a?(AST::Types::Nil)
361
+ truthy_types = [] #: Array[AST::Types::t]
362
+ falsy_types = [] #: Array[AST::Types::t]
363
+
364
+ type.types.each do |type|
365
+ truthy, falsy = partition_union(type)
366
+
367
+ truthy_types << truthy if truthy
368
+ falsy_types << falsy if falsy
364
369
  end
365
370
 
366
371
  [
367
372
  truthy_types.empty? ? nil : AST::Types::Union.build(types: truthy_types),
368
373
  falsy_types.empty? ? nil : AST::Types::Union.build(types: falsy_types)
369
374
  ]
370
- when AST::Types::Any, AST::Types::Boolean
375
+ when AST::Types::Any, AST::Types::Boolean, AST::Types::Top, AST::Types::Logic::Base
371
376
  [type, type]
372
377
  when AST::Types::Nil
373
378
  [nil, type]
@@ -1398,8 +1398,11 @@ module Steep
1398
1398
  when :true, :false
1399
1399
  ty = node.type == :true ? AST::Types::Literal.new(value: true) : AST::Types::Literal.new(value: false)
1400
1400
 
1401
- if hint && check_relation(sub_type: ty, super_type: hint).success? && !hint.is_a?(AST::Types::Any) && !hint.is_a?(AST::Types::Top)
1401
+ case
1402
+ when hint && check_relation(sub_type: ty, super_type: hint).success? && !hint.is_a?(AST::Types::Any) && !hint.is_a?(AST::Types::Top)
1402
1403
  add_typing(node, type: hint)
1404
+ when condition
1405
+ add_typing(node, type: ty)
1403
1406
  else
1404
1407
  add_typing(node, type: AST::Types::Boolean.new)
1405
1408
  end
@@ -1920,18 +1923,9 @@ module Steep
1920
1923
  cond_vars.delete(name)
1921
1924
  end
1922
1925
 
1923
- var_name = :"_a#{SecureRandom.alphanumeric(4)}"
1924
- var_cond, value_node = extract_outermost_call(cond, var_name)
1925
- if value_node
1926
- unless constr.context.type_env[value_node]
1927
- constr = constr.update_type_env do |env|
1928
- env.assign_local_variable(var_name, cond_type, nil)
1929
- end
1930
- cond = var_cond
1931
- else
1932
- value_node = nil
1933
- end
1934
- end
1926
+ var_name = :"_a[#{SecureRandom.alphanumeric(4)}]"
1927
+ var_cond, value_node = transform_condition_node(cond, var_name)
1928
+ constr = constr.update_type_env {|env| env.assign_local_variable(var_name, cond_type, nil) }
1935
1929
 
1936
1930
  next_branch_reachable = true
1937
1931
 
@@ -1949,12 +1943,12 @@ module Steep
1949
1943
  false_branch_reachable = false
1950
1944
 
1951
1945
  tests.each do |test|
1952
- test_node = test.updated(:send, [test, :===, cond])
1946
+ test_node = test.updated(:send, [test, :===, var_cond])
1953
1947
  test_type, test_constr = test_constr.synthesize(test_node, condition: true).to_ary
1954
1948
  truthy, falsy = interpreter.eval(node: test_node, env: test_constr.context.type_env)
1955
1949
 
1956
- truthy_env = truthy.env
1957
- falsy_env = falsy.env
1950
+ truthy_env = propagate_type_env(var_name, value_node, truthy.env)
1951
+ falsy_env = propagate_type_env(var_name, value_node, falsy.env)
1958
1952
 
1959
1953
  test_envs << truthy_env
1960
1954
 
@@ -2003,11 +1997,6 @@ module Steep
2003
1997
  types = branch_results.map(&:type)
2004
1998
  constrs = branch_results.map(&:constr)
2005
1999
 
2006
- cond_type = when_constr.context.type_env[var_name]
2007
- cond_type ||= when_constr.context.type_env[cond_vars.first || raise] unless cond_vars.empty?
2008
- cond_type ||= when_constr.context.type_env[value_node] if value_node
2009
- cond_type ||= typing.type_of(node: node.children[0])
2010
-
2011
2000
  if !next_branch_reachable
2012
2001
  # Exhaustive
2013
2002
  _, _, _, loc = deconstruct_case_node!(node)
@@ -2030,9 +2019,6 @@ module Steep
2030
2019
  branch_results = [] #: Array[Pair]
2031
2020
 
2032
2021
  condition_constr = constr
2033
- clause_constr = constr
2034
-
2035
- next_branch_reachable = true
2036
2022
 
2037
2023
  whens.each do |when_clause|
2038
2024
  when_clause_constr = condition_constr
@@ -2043,7 +2029,6 @@ module Steep
2043
2029
  *tests, body = when_clause.children
2044
2030
 
2045
2031
  branch_reachable = false
2046
- false_branch_reachable = false
2047
2032
 
2048
2033
  tests.each do |test|
2049
2034
  test_type, condition_constr = condition_constr.synthesize(test, condition: true)
@@ -2054,12 +2039,9 @@ module Steep
2054
2039
  condition_constr = condition_constr.update_type_env { falsy_env }
2055
2040
  body_envs << truthy_env
2056
2041
 
2057
- branch_reachable ||= next_branch_reachable && !truthy.unreachable
2058
- false_branch_reachable ||= !falsy.unreachable
2042
+ branch_reachable ||= !truthy.unreachable
2059
2043
  end
2060
2044
 
2061
- next_branch_reachable &&= false_branch_reachable
2062
-
2063
2045
  if body
2064
2046
  branch_results <<
2065
2047
  when_clause_constr
@@ -4490,16 +4472,27 @@ module Steep
4490
4472
  end
4491
4473
 
4492
4474
  def union_type_unify(*types)
4493
- types.inject do |type1, type2|
4494
- unless no_subtyping?(sub_type: type1, super_type: type2)
4495
- next type2
4496
- end
4475
+ types = types.reject {|t| t.is_a?(AST::Types::Bot) }
4497
4476
 
4498
- unless no_subtyping?(sub_type: type2, super_type: type1)
4499
- next type1
4500
- end
4477
+ if types.empty?
4478
+ AST::Types::Bot.new
4479
+ else
4480
+ types.inject do |type1, type2|
4481
+ next type2 if type1.is_a?(AST::Types::Any)
4482
+ next type1 if type2.is_a?(AST::Types::Any)
4501
4483
 
4502
- union_type(type1, type2)
4484
+ unless no_subtyping?(sub_type: type1, super_type: type2)
4485
+ # type1 <: type2
4486
+ next type2
4487
+ end
4488
+
4489
+ unless no_subtyping?(sub_type: type2, super_type: type1)
4490
+ # type2 <: type1
4491
+ next type1
4492
+ end
4493
+
4494
+ union_type(type1, type2)
4495
+ end
4503
4496
  end
4504
4497
  end
4505
4498
 
@@ -5029,33 +5022,19 @@ module Steep
5029
5022
  with_new_typing(typing.parent || raise)
5030
5023
  end
5031
5024
 
5032
- def extract_outermost_call(node, var_name)
5025
+ def transform_condition_node(node, var_name)
5033
5026
  case node.type
5034
5027
  when :lvasgn
5035
5028
  name, rhs = node.children
5036
- rhs, value_node = extract_outermost_call(rhs, var_name)
5037
- if value_node
5038
- [node.updated(nil, [name, rhs]), value_node]
5039
- else
5040
- [node, value_node]
5041
- end
5029
+ rhs, value_node = transform_condition_node(rhs, var_name)
5030
+ [node.updated(nil, [name, rhs]), value_node]
5042
5031
  when :begin
5043
5032
  *children, last = node.children
5044
- last, value_node = extract_outermost_call(last, var_name)
5045
- if value_node
5046
- [node.updated(nil, children.push(last)), value_node]
5047
- else
5048
- [node, value_node]
5049
- end
5050
- when :lvar
5051
- [node, nil]
5033
+ last, value_node = transform_condition_node(last, var_name)
5034
+ [node.updated(nil, children.push(last)), value_node]
5052
5035
  else
5053
- if value_node?(node)
5054
- [node, nil]
5055
- else
5056
- var_node = node.updated(:lvar, [var_name])
5057
- [var_node, node]
5058
- end
5036
+ var_node = node.updated(:lvar, [var_name])
5037
+ [var_node, node]
5059
5038
  end
5060
5039
  end
5061
5040
 
@@ -5109,5 +5088,20 @@ module Steep
5109
5088
  end
5110
5089
  end
5111
5090
  end
5091
+
5092
+ def propagate_type_env(source, dest, env)
5093
+ source_type = env[source] or raise
5094
+
5095
+ if dest.type == :lvar
5096
+ var_name = dest.children[0] #: Symbol
5097
+ env.assign_local_variable(var_name, source_type, nil)
5098
+ else
5099
+ if env[dest]
5100
+ env.replace_pure_call_type(dest, source_type)
5101
+ else
5102
+ env
5103
+ end
5104
+ end
5105
+ end
5112
5106
  end
5113
5107
  end
@@ -417,6 +417,10 @@ module Steep
417
417
  end
418
418
 
419
419
  [truthy_types, falsy_types]
420
+ when AST::Types::Boolean
421
+ [[arg_type], [arg_type]]
422
+ when AST::Types::Top, AST::Types::Any
423
+ [[arg_type], [arg_type]]
420
424
  else
421
425
  types = [arg_type]
422
426
 
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.5.0.pre.3"
2
+ VERSION = "1.5.0.pre.4"
3
3
  end
@@ -538,18 +538,30 @@ module Steep
538
538
  # Returns a pair of transformed node and the outer most call/non-value node if present.
539
539
  #
540
540
  # ```rb
541
- # x = y = foo() # Call `#transform_value_node` with the node and var_name `:__foo__`
541
+ # x = y = foo() # Call `#transform_condition_node` with the node and var_name `:__foo__`
542
542
  # # => Returns [x = y = __foo__, foo()]
543
+ #
544
+ # x # Call `#transform_condition_node` with the node and var_name `:__foo__`
545
+ # # => Returns [__foo__, x]
543
546
  # ```
544
547
  #
545
548
  # This is typically used for transforming assginment node for case condition.
546
549
  #
547
- def extract_outermost_call: (Parser::AST::Node node, Symbol) -> [Parser::AST::Node, Parser::AST::Node?]
550
+ def transform_condition_node: (Parser::AST::Node node, Symbol) -> [Parser::AST::Node, Parser::AST::Node]
548
551
 
549
552
  def type_name: (AST::Types::t) -> RBS::TypeName?
550
553
 
551
554
  def singleton_type: (AST::Types::t) -> AST::Types::t?
552
555
 
553
556
  def instance_type: (AST::Types::t) -> AST::Types::t?
557
+
558
+ # Propagate an entry of `source` in TypeEnv to `dest`
559
+ #
560
+ # `source` is name of a local variable.
561
+ #
562
+ # If `dest` is a `lvar` node, it updates local variable entry of TypeEnv.
563
+ # Otherwise, it updates *pure* call of `dest` if it already exists.
564
+ #
565
+ def propagate_type_env: (Symbol source, Parser::AST::Node dest, TypeInference::TypeEnv) -> TypeInference::TypeEnv
554
566
  end
555
567
  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: 1.5.0.pre.3
4
+ version: 1.5.0.pre.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-05 00:00:00.000000000 Z
11
+ date: 2023-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser