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

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: 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