steep 0.21.0 → 0.27.0

Sign up to get free protection for your applications and to get access to all the features.
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