steep 0.21.0 → 0.27.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -1
  3. data/Gemfile +7 -0
  4. data/bin/steep-prof +16 -0
  5. data/lib/steep/ast/types.rb +5 -3
  6. data/lib/steep/ast/types/any.rb +1 -3
  7. data/lib/steep/ast/types/boolean.rb +1 -3
  8. data/lib/steep/ast/types/bot.rb +1 -3
  9. data/lib/steep/ast/types/class.rb +2 -2
  10. data/lib/steep/ast/types/factory.rb +58 -16
  11. data/lib/steep/ast/types/helper.rb +6 -0
  12. data/lib/steep/ast/types/instance.rb +2 -2
  13. data/lib/steep/ast/types/intersection.rb +8 -4
  14. data/lib/steep/ast/types/literal.rb +5 -3
  15. data/lib/steep/ast/types/name.rb +13 -9
  16. data/lib/steep/ast/types/nil.rb +1 -3
  17. data/lib/steep/ast/types/proc.rb +5 -2
  18. data/lib/steep/ast/types/record.rb +9 -4
  19. data/lib/steep/ast/types/self.rb +1 -1
  20. data/lib/steep/ast/types/top.rb +1 -3
  21. data/lib/steep/ast/types/tuple.rb +5 -3
  22. data/lib/steep/ast/types/union.rb +11 -3
  23. data/lib/steep/ast/types/var.rb +2 -2
  24. data/lib/steep/ast/types/void.rb +1 -3
  25. data/lib/steep/drivers/check.rb +4 -0
  26. data/lib/steep/interface/method_type.rb +48 -18
  27. data/lib/steep/interface/substitution.rb +32 -2
  28. data/lib/steep/project/target.rb +17 -3
  29. data/lib/steep/server/base_worker.rb +4 -3
  30. data/lib/steep/server/master.rb +3 -1
  31. data/lib/steep/server/signature_worker.rb +3 -0
  32. data/lib/steep/signature/errors.rb +28 -0
  33. data/lib/steep/signature/validator.rb +11 -1
  34. data/lib/steep/source.rb +2 -1
  35. data/lib/steep/subtyping/check.rb +38 -21
  36. data/lib/steep/type_construction.rb +446 -181
  37. data/lib/steep/type_inference/constant_env.rb +1 -1
  38. data/lib/steep/type_inference/context.rb +8 -0
  39. data/lib/steep/type_inference/context_array.rb +4 -3
  40. data/lib/steep/type_inference/logic.rb +31 -0
  41. data/lib/steep/typing.rb +7 -0
  42. data/lib/steep/version.rb +1 -1
  43. data/smoke/hash/d.rb +1 -1
  44. data/steep.gemspec +1 -8
  45. metadata +5 -88
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6109c6ce90265363be0ef33fe06e517577f3e884a6fc20c921f5d716c4916de1
4
- data.tar.gz: 1bcba16bfab23e534eb40b7302dd21e43b487ba6441a02d0da403ac4df54d788
3
+ metadata.gz: '09e364b23ebecd35868dbde7ea09938fa8208219ee1fcd19a0faaa9a160f6aab'
4
+ data.tar.gz: c4374adcf1b0c54663e04380229322d9c07865fac69b1b74fa2eeabecd26cd7d
5
5
  SHA512:
6
- metadata.gz: b8bffda05cd158a3ce849fca2722fcb0d62de0d6307a88d4fa0d3758a7965aef706bccab3b4a634a3343e2c0bbd1cc87bec8e5f5b31cfa52e19a6d3f2931b5eb
7
- data.tar.gz: 57cb080c69a71fb31f52bd4e65e37ca1719f46718b02632d2c5af3ff72c8b34eba56f098831558fd7df18afbdec0fd6802d0fbb326c5cb4086c147ba11b5447f
6
+ metadata.gz: e59635b6fba6e2dac0c7ba8fb12d9a4e4734ffd95a48b8af1cb2cdbb0a5280d660c46fbf724ea48a61247165319b448598f702d6ef0dbf78d28b78dcb7ba536c
7
+ data.tar.gz: 62ca2d4504a4d75922abf3b76def89f0146a298b3452a874d98a869fa3f39942984224324cdec93f7894918b4386a07aabb4a1be6f572bcbbb5d3081086b1cda
@@ -2,6 +2,43 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.27.0 (2020-08-31)
6
+
7
+ * Make tuple types _covariant_ ([#195](https://github.com/soutaro/steep/pull/195))
8
+ * Support `or_asgn`/`and_asgn` with `send` node lhs ([#194](https://github.com/soutaro/steep/pull/194))
9
+ * Performance improvement ([#193](https://github.com/soutaro/steep/pull/193))
10
+ * Add specialized versions of `#first` and `#last` on tuples ([#191](https://github.com/soutaro/steep/pull/191))
11
+ * Typing bug fix on `[]` (empty array) ([#190](https://github.com/soutaro/steep/pull/190))
12
+ * Earlier shutdown with interruption while `steep watch` ([#173](https://github.com/soutaro/steep/pull/173))
13
+
14
+ ## 0.26.0
15
+
16
+ * Skipped
17
+
18
+ ## 0.25.0 (2020-08-18)
19
+
20
+ * Improve `op_send` typing ([#186](https://github.com/soutaro/steep/pull/186))
21
+ * Improve `op_asgn` typing ([#189](https://github.com/soutaro/steep/pull/189))
22
+ * Better multi-assignment support ([#183](https://github.com/soutaro/steep/pull/183), [#184](https://github.com/soutaro/steep/pull/184))
23
+ * Support for loop and class variables ([#182](https://github.com/soutaro/steep/pull/182))
24
+ * Fix tuple typing ([#181](https://github.com/soutaro/steep/pull/181))
25
+
26
+ ## 0.24.0 (2020-08-11)
27
+
28
+ * Update RBS to 0.10 ([#180](https://github.com/soutaro/steep/pull/180))
29
+
30
+ ## 0.23.0 (2020-08-06)
31
+
32
+ * Fix literal typing with hint ([#179](https://github.com/soutaro/steep/pull/179))
33
+ * Fix literal type subtyping ([#178](https://github.com/soutaro/steep/pull/178))
34
+
35
+ ## 0.22.0 (2020-08-03)
36
+
37
+ * Improve signature validation ([#175](https://github.com/soutaro/steep/pull/175), [#177](https://github.com/soutaro/steep/pull/177))
38
+ * Fix boolean literal typing ([#172](https://github.com/soutaro/steep/pull/172))
39
+ * Make exit code success when Steep has unreported type errors ([#171](https://github.com/soutaro/steep/pull/171))
40
+ * Allow `./` prefix for signature pattern ([#170](https://github.com/soutaro/steep/pull/170))
41
+
5
42
  ## 0.21.0 (2020-07-20)
6
43
 
7
44
  * Fix LSP hover ([#168](https://github.com/soutaro/steep/pull/168))
@@ -44,7 +81,7 @@
44
81
 
45
82
  * Fix constant resolution ([#143](https://github.com/soutaro/steep/pull/143))
46
83
  * Fix RBS diagnostics line number in LSP ([#142](https://github.com/soutaro/steep/pull/142))
47
- * Fix crash caused by hover on `def` in LSP ([#140](https://github.com/soutaro/steep/pull/140))
84
+ * Fix crash caused by hover on `def` in LSP ([#140](https://github.com/soutaro/steep/pull/140))
48
85
 
49
86
  ## 0.16.0 (2020-05-19)
50
87
 
data/Gemfile CHANGED
@@ -5,3 +5,10 @@ gemspec
5
5
 
6
6
  gem "with_steep_types", path: "test/gems/with_steep_types"
7
7
  gem "without_steep_types", path: "test/gems/without_steep_types"
8
+
9
+ gem "rake"
10
+ gem "minitest", "~> 5.0"
11
+ gem "racc", "~> 1.4"
12
+ gem "minitest-reporters"
13
+ gem "minitest-hooks"
14
+ gem "stackprof"
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "stackprof"
4
+
5
+ mode = (ENV["STEEP_STACKPROF_MODE"] || :wall).to_sym
6
+ out = ENV["STEEP_STACKPROF_OUT"] || "tmp/stackprof-#{mode}-steep.dump"
7
+
8
+ def exit(*)
9
+
10
+ end
11
+
12
+
13
+ STDERR.puts "Running profiler: mode=#{mode}, out=#{out}"
14
+ StackProf.run(mode: mode, out: out) do
15
+ load File.join(__dir__, "../exe/steep")
16
+ end
@@ -35,9 +35,11 @@ module Steep
35
35
  "masked(#{type}|#{mask})"
36
36
  end
37
37
 
38
- def free_variables(set = Set.new)
39
- type.free_variables(set)
40
- mask.free_variables(set)
38
+ def free_variables
39
+ @fvs ||= Set.new.tap do |set|
40
+ set.merge(type.free_variables)
41
+ set.merge(mask.free_variables)
42
+ end
41
43
  end
42
44
 
43
45
  def each_type(&block)
@@ -26,9 +26,7 @@ module Steep
26
26
  "untyped"
27
27
  end
28
28
 
29
- def free_variables
30
- Set.new
31
- end
29
+ include Helper::NoFreeVariables
32
30
 
33
31
  def level
34
32
  [1]
@@ -26,9 +26,7 @@ module Steep
26
26
  "bool"
27
27
  end
28
28
 
29
- def free_variables
30
- Set.new
31
- end
29
+ include Helper::NoFreeVariables
32
30
 
33
31
  def level
34
32
  [0]
@@ -26,9 +26,7 @@ module Steep
26
26
  "⟘"
27
27
  end
28
28
 
29
- def free_variables
30
- Set.new
31
- end
29
+ include Helper::NoFreeVariables
32
30
 
33
31
  def level
34
32
  [2]
@@ -22,8 +22,8 @@ module Steep
22
22
  s.module_type or raise "Unexpected substitution: #{inspect}"
23
23
  end
24
24
 
25
- def free_variables
26
- Set.new
25
+ def free_variables()
26
+ @fvs = Set.new([self])
27
27
  end
28
28
 
29
29
  def level
@@ -4,8 +4,14 @@ module Steep
4
4
  class Factory
5
5
  attr_reader :definition_builder
6
6
 
7
+ attr_reader :type_name_cache
8
+ attr_reader :type_cache
9
+
7
10
  def initialize(builder:)
8
11
  @definition_builder = builder
12
+
13
+ @type_name_cache = {}
14
+ @type_cache = {}
9
15
  end
10
16
 
11
17
  def type_name_resolver
@@ -13,7 +19,9 @@ module Steep
13
19
  end
14
20
 
15
21
  def type(type)
16
- case type
22
+ ty = type_cache[type] and return ty
23
+
24
+ type_cache[type] = case type
17
25
  when RBS::Types::Bases::Any
18
26
  Any.new(location: nil)
19
27
  when RBS::Types::Bases::Class
@@ -144,14 +152,17 @@ module Steep
144
152
  end
145
153
 
146
154
  def type_name(name)
147
- case
148
- when name.class?
149
- Names::Module.new(name: name.name, namespace: namespace(name.namespace), location: nil)
150
- when name.interface?
151
- Names::Interface.new(name: name.name, namespace: namespace(name.namespace), location: nil)
152
- when name.alias?
153
- Names::Alias.new(name: name.name, namespace: namespace(name.namespace), location: nil)
154
- end
155
+ n = type_name_cache[name] and return n
156
+
157
+ type_name_cache[name] =
158
+ (case
159
+ when name.class?
160
+ Names::Module.new(name: name.name, namespace: namespace(name.namespace), location: nil)
161
+ when name.interface?
162
+ Names::Interface.new(name: name.name, namespace: namespace(name.namespace), location: nil)
163
+ when name.alias?
164
+ Names::Alias.new(name: name.name, namespace: namespace(name.namespace), location: nil)
165
+ end)
155
166
  end
156
167
 
157
168
  def type_name_1(name)
@@ -190,7 +201,7 @@ module Steep
190
201
  )
191
202
  end
192
203
 
193
- def method_type(method_type, self_type:)
204
+ def method_type(method_type, self_type:, subst2: nil)
194
205
  fvs = self_type.free_variables()
195
206
 
196
207
  type_params = []
@@ -208,6 +219,7 @@ module Steep
208
219
  end
209
220
  end
210
221
  subst = Interface::Substitution.build(alpha_vars, alpha_types)
222
+ subst.merge!(subst2) if subst2
211
223
 
212
224
  type = Interface::MethodType.new(
213
225
  type_params: type_params,
@@ -288,7 +300,7 @@ module Steep
288
300
  def expand_alias(type)
289
301
  unfolded = case type
290
302
  when AST::Types::Name::Alias
291
- unfolded = unfold(type.name)
303
+ unfold(type.name)
292
304
  else
293
305
  type
294
306
  end
@@ -332,7 +344,7 @@ module Steep
332
344
 
333
345
  interface.methods[name] = Interface::Interface::Combination.overload(
334
346
  method.method_types.map do |type|
335
- method_type(type, self_type: self_type) {|ty| ty.subst(subst) }
347
+ method_type(type, self_type: self_type, subst2: subst)
336
348
  end,
337
349
  incompatible: name == :initialize || name == :new
338
350
  )
@@ -353,9 +365,9 @@ module Steep
353
365
  definition.methods.each do |name, method|
354
366
  interface.methods[name] = Interface::Interface::Combination.overload(
355
367
  method.method_types.map do |type|
356
- method_type(type, self_type: self_type) {|type| type.subst(subst) }
368
+ method_type(type, self_type: self_type, subst2: subst)
357
369
  end,
358
- incompatible: method.attributes.include?(:incompatible)
370
+ incompatible: false
359
371
  )
360
372
  end
361
373
  end
@@ -379,9 +391,9 @@ module Steep
379
391
 
380
392
  interface.methods[name] = Interface::Interface::Combination.overload(
381
393
  method.method_types.map do |type|
382
- method_type(type, self_type: self_type) {|type| type.subst(subst) }
394
+ method_type(type, self_type: self_type, subst2: subst)
383
395
  end,
384
- incompatible: method.attributes.include?(:incompatible)
396
+ incompatible: false
385
397
  )
386
398
  end
387
399
  end
@@ -468,6 +480,36 @@ module Steep
468
480
  incompatible: false
469
481
  )
470
482
  end
483
+
484
+ array_interface.methods[:first] = array_interface.methods[:first].yield_self do |first|
485
+ Interface::Interface::Combination.overload(
486
+ [
487
+ Interface::MethodType.new(
488
+ type_params: [],
489
+ params: Interface::Params.empty,
490
+ block: nil,
491
+ return_type: type.types[0] || AST::Builtin.nil_type,
492
+ location: nil
493
+ )
494
+ ],
495
+ incompatible: false
496
+ )
497
+ end
498
+
499
+ array_interface.methods[:last] = array_interface.methods[:last].yield_self do |last|
500
+ Interface::Interface::Combination.overload(
501
+ [
502
+ Interface::MethodType.new(
503
+ type_params: [],
504
+ params: Interface::Params.empty,
505
+ block: nil,
506
+ return_type: type.types.last || AST::Builtin.nil_type,
507
+ location: nil
508
+ )
509
+ ],
510
+ incompatible: false
511
+ )
512
+ end
471
513
  end
472
514
  end
473
515
 
@@ -15,6 +15,12 @@ module Steep
15
15
  end || []
16
16
  end
17
17
  end
18
+
19
+ module NoFreeVariables
20
+ def free_variables()
21
+ @fvs ||= Set.new
22
+ end
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -22,8 +22,8 @@ module Steep
22
22
  s.instance_type or raise "Unexpected substitution: #{inspect}"
23
23
  end
24
24
 
25
- def free_variables
26
- Set.new
25
+ def free_variables()
26
+ @fvs = Set.new([self])
27
27
  end
28
28
 
29
29
  def to_s
@@ -57,10 +57,14 @@ module Steep
57
57
  "(#{types.map(&:to_s).sort.join(" & ")})"
58
58
  end
59
59
 
60
- def free_variables
61
- types.each.with_object(Set.new) do |type, set|
62
- set.merge(type.free_variables)
63
- end
60
+ def free_variables()
61
+ @fvs ||= begin
62
+ set = Set.new
63
+ types.each do |type|
64
+ set.merge(type.free_variables)
65
+ end
66
+ set
67
+ end
64
68
  end
65
69
 
66
70
  include Helper::ChildrenLevel
@@ -29,9 +29,7 @@ module Steep
29
29
  value.inspect
30
30
  end
31
31
 
32
- def free_variables
33
- Set.new
34
- end
32
+ include Helper::NoFreeVariables
35
33
 
36
34
  def level
37
35
  [0]
@@ -49,6 +47,10 @@ module Steep
49
47
  Builtin::String
50
48
  when Symbol
51
49
  Builtin::Symbol
50
+ when true
51
+ Builtin::TrueClass
52
+ when false
53
+ Builtin::FalseClass
52
54
  else
53
55
  raise "Unexpected literal type: #{value.inspect}"
54
56
  end
@@ -11,9 +11,7 @@ module Steep
11
11
  @name = name
12
12
  end
13
13
 
14
- def free_variables
15
- Set.new
16
- end
14
+ include Helper::NoFreeVariables
17
15
 
18
16
  def subst(s)
19
17
  self
@@ -41,7 +39,7 @@ module Steep
41
39
  alias eql? ==
42
40
 
43
41
  def hash
44
- self.class.hash ^ name.hash ^ args.hash
42
+ @hash ||= self.class.hash ^ name.hash ^ args.hash
45
43
  end
46
44
 
47
45
  def to_s
@@ -57,14 +55,20 @@ module Steep
57
55
  end
58
56
 
59
57
  def subst(s)
60
- self.class.new(location: location,
61
- name: name,
62
- args: args.map {|a| a.subst(s) })
58
+ if free_variables.intersect?(s.domain)
59
+ self.class.new(location: location,
60
+ name: name,
61
+ args: args.map {|a| a.subst(s) })
62
+ else
63
+ self
64
+ end
63
65
  end
64
66
 
65
67
  def free_variables
66
- args.each.with_object(Set.new) do |type, vars|
67
- vars.merge(type.free_variables)
68
+ @fvs ||= Set.new().tap do |set|
69
+ args.each do |type|
70
+ set.merge(type.free_variables)
71
+ end
68
72
  end
69
73
  end
70
74
 
@@ -26,9 +26,7 @@ module Steep
26
26
  "nil"
27
27
  end
28
28
 
29
- def free_variables
30
- Set.new
31
- end
29
+ include Helper::NoFreeVariables
32
30
 
33
31
  def level
34
32
  [0]
@@ -36,8 +36,11 @@ module Steep
36
36
  "^#{params} -> #{return_type}"
37
37
  end
38
38
 
39
- def free_variables
40
- params.free_variables + return_type.free_variables
39
+ def free_variables()
40
+ @fvs ||= Set.new.tap do |set|
41
+ set.merge(params.free_variables)
42
+ set.merge(return_type.free_variables)
43
+ end
41
44
  end
42
45
 
43
46
  def level
@@ -26,12 +26,17 @@ module Steep
26
26
  end
27
27
 
28
28
  def to_s
29
- "{ #{elements.map {|key, value| "#{key.inspect} => #{value}" }.join(", ")} }"
29
+ strings = elements.keys.sort.map do |key|
30
+ "#{key.inspect} => #{elements[key]}"
31
+ end
32
+ "{ #{strings.join(", ")} }"
30
33
  end
31
34
 
32
- def free_variables
33
- elements.each_value.with_object(Set.new) do |type, set|
34
- set.merge(type.free_variables)
35
+ def free_variables()
36
+ @fvs ||= Set.new.tap do |set|
37
+ elements.each_value do |type|
38
+ set.merge(type.free_variables)
39
+ end
35
40
  end
36
41
  end
37
42