steep 0.47.1 → 0.48.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -102,6 +102,36 @@ module Steep
102
102
  end
103
103
  end
104
104
 
105
+ class TypeVariableContext
106
+ attr_reader :table
107
+ attr_reader :type_params
108
+
109
+ def initialize(type_params, parent_context: nil)
110
+ @type_params = type_params
111
+
112
+ @table = {}
113
+ table.merge!(parent_context.table) if parent_context
114
+
115
+ type_params.each do |param|
116
+ table[param.name] = param
117
+ end
118
+ end
119
+
120
+ def [](name)
121
+ table[name].upper_bound
122
+ end
123
+
124
+ def upper_bounds
125
+ table.each_value.with_object({}) do |type_param, bounds|
126
+ bounds[type_param.name] = type_param.upper_bound
127
+ end
128
+ end
129
+
130
+ def self.empty
131
+ new([])
132
+ end
133
+ end
134
+
105
135
  attr_reader :call_context
106
136
  attr_reader :method_context
107
137
  attr_reader :block_context
@@ -110,8 +140,9 @@ module Steep
110
140
  attr_reader :self_type
111
141
  attr_reader :type_env
112
142
  attr_reader :lvar_env
143
+ attr_reader :variable_context
113
144
 
114
- def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:, call_context:)
145
+ def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:, call_context:, variable_context:)
115
146
  @method_context = method_context
116
147
  @block_context = block_context
117
148
  @break_context = break_context
@@ -120,6 +151,7 @@ module Steep
120
151
  @type_env = type_env
121
152
  @lvar_env = lvar_env
122
153
  @call_context = call_context
154
+ @variable_context = variable_context
123
155
  end
124
156
 
125
157
  def with(method_context: self.method_context,
@@ -129,7 +161,8 @@ module Steep
129
161
  self_type: self.self_type,
130
162
  type_env: self.type_env,
131
163
  lvar_env: self.lvar_env,
132
- call_context: self.call_context)
164
+ call_context: self.call_context,
165
+ variable_context: self.variable_context)
133
166
  self.class.new(
134
167
  method_context: method_context,
135
168
  block_context: block_context,
@@ -138,7 +171,8 @@ module Steep
138
171
  self_type: self_type,
139
172
  type_env: type_env,
140
173
  lvar_env: lvar_env,
141
- call_context: call_context
174
+ call_context: call_context,
175
+ variable_context: variable_context
142
176
  )
143
177
  end
144
178
  end
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.47.1"
2
+ VERSION = "0.48.0"
3
3
  end
data/lib/steep.rb CHANGED
@@ -50,16 +50,17 @@ require "steep/ast/types/factory"
50
50
 
51
51
  require "steep/range_extension"
52
52
 
53
+ require "steep/interface/type_param"
53
54
  require "steep/interface/function"
54
55
  require "steep/interface/block"
55
56
  require "steep/interface/method_type"
56
57
  require "steep/interface/substitution"
57
58
  require "steep/interface/interface"
58
59
 
59
- require "steep/subtyping/check"
60
60
  require "steep/subtyping/result"
61
+ require "steep/subtyping/check"
62
+ require "steep/subtyping/cache"
61
63
  require "steep/subtyping/relation"
62
- require "steep/subtyping/trace"
63
64
  require "steep/subtyping/constraints"
64
65
  require "steep/subtyping/variable_variance"
65
66
  require "steep/subtyping/variable_occurrence"
@@ -123,7 +124,6 @@ require "steep/drivers/validate"
123
124
  require "steep/drivers/annotations"
124
125
  require "steep/drivers/watch"
125
126
  require "steep/drivers/langserver"
126
- require "steep/drivers/trace_printer"
127
127
  require "steep/drivers/print_project"
128
128
  require "steep/drivers/init"
129
129
  require "steep/drivers/vendor"
@@ -0,0 +1,35 @@
1
+ class LengthCalculator
2
+ def max0(x, y)
3
+ if x.size > y.size
4
+ x
5
+ else
6
+ y
7
+ end
8
+ end
9
+
10
+ def max1(x, y)
11
+ if x.size > y.size
12
+ x
13
+ else
14
+ y
15
+ end
16
+ end
17
+
18
+ def max2(x, y)
19
+ if x.size > y.size
20
+ x
21
+ else
22
+ y
23
+ end
24
+ end
25
+ end
26
+
27
+ calc = LengthCalculator.new()
28
+
29
+ calc.max0("foo", "bar")
30
+ calc.max1("foo", "bar")
31
+ calc.max2("foo", "bar")
32
+
33
+ calc.max0(true, false)
34
+ calc.max1(true, false)
35
+ calc.max2(true, false)
@@ -0,0 +1,34 @@
1
+ # LengthCalculator shows three different method types having the same implementation.
2
+ #
3
+ # * It receives two objects.
4
+ # * It calls the `#size` method of the objects, and compare the return values.
5
+ # * It returns one of the objects which has bigger `#size` value.
6
+ #
7
+ class LengthCalculator
8
+ interface _Sized
9
+ def size: () -> Integer
10
+ end
11
+
12
+ # *Untyped* version -- all (static) type information is lost.
13
+ #
14
+ # You can pass any object, even if the object doesn't have `#size` method.
15
+ #
16
+ def max0: (untyped, untyped) -> untyped
17
+
18
+ # *Subtyping* version -- with constraints on arguments, but the return type is inaccurate.
19
+ #
20
+ # You can type check if the object has `#size` method of the expected type.
21
+ # However, the return type also has `_Sized` type, which drops other methods than `#size`.
22
+ #
23
+ def max1: (_Sized, _Sized) -> _Sized
24
+
25
+ # *Generics* version -- the most advanced one in Steep/RBS
26
+ #
27
+ # You can type check if the object has `#size` method of the expected type.
28
+ # And the return type is the one given as arguments.
29
+ #
30
+ # Note that the type system of Steep cannot ensure the given two objects have the same type.
31
+ # Passing `String` and `Array[String]` will infer the return type `String | Array[String]`.
32
+ #
33
+ def max2: [T < _Sized] (T, T) -> T
34
+ end
@@ -0,0 +1,3 @@
1
+ module NonregularTypeAlias
2
+ type t[T, S] = ^() -> t[String, Integer]
3
+ end
@@ -0,0 +1,3 @@
1
+ type foo = bar
2
+ type bar = baz
3
+ type baz = foo
@@ -103,6 +103,31 @@
103
103
  message: The variance of type parameter `A` is covariant, but used in incompatible
104
104
  position here
105
105
  code: RBS::InvalidVarianceAnnotation
106
+ - file: mixin-class-error.rbs
107
+ diagnostics:
108
+ - range:
109
+ start:
110
+ line: 5
111
+ character: 2
112
+ end:
113
+ line: 5
114
+ character: 13
115
+ severity: ERROR
116
+ message: Cannot include a class `::Foo` in the definition of `::Bar`
117
+ code: RBS::MixinClassError
118
+ - file: nonregular-type-alias.rbs
119
+ diagnostics:
120
+ - range:
121
+ start:
122
+ line: 2
123
+ character: 2
124
+ end:
125
+ line: 2
126
+ character: 42
127
+ severity: ERROR
128
+ message: 'Type alias ::NonregularTypeAlias::t is defined *non-regular*: ::NonregularTypeAlias::t[::String,
129
+ ::Integer]'
130
+ code: RBS::NonregularTypeAlias
106
131
  - file: recursive-alias.rbs
107
132
  diagnostics:
108
133
  - range:
@@ -151,6 +176,38 @@
151
176
  message: 'Circular inheritance/mix-in is detected: ::Baz <: ::Foo <: ::Bar <:
152
177
  ::Baz'
153
178
  code: RBS::RecursiveAncestor
179
+ - file: recursive-type-alias.rbs
180
+ diagnostics:
181
+ - range:
182
+ start:
183
+ line: 1
184
+ character: 0
185
+ end:
186
+ line: 1
187
+ character: 14
188
+ severity: ERROR
189
+ message: 'Type aliases cannot be *directly recursive*: ::foo'
190
+ code: RBS::RecursiveTypeAlias
191
+ - range:
192
+ start:
193
+ line: 2
194
+ character: 0
195
+ end:
196
+ line: 2
197
+ character: 14
198
+ severity: ERROR
199
+ message: 'Type aliases cannot be *directly recursive*: ::bar'
200
+ code: RBS::RecursiveTypeAlias
201
+ - range:
202
+ start:
203
+ line: 3
204
+ character: 0
205
+ end:
206
+ line: 3
207
+ character: 14
208
+ severity: ERROR
209
+ message: 'Type aliases cannot be *directly recursive*: ::baz'
210
+ code: RBS::RecursiveTypeAlias
154
211
  - file: superclass-mismatch.rbs
155
212
  diagnostics:
156
213
  - range:
@@ -229,15 +286,3 @@
229
286
  severity: ERROR
230
287
  message: Cannot find type `ZZZ`
231
288
  code: RBS::UnknownTypeName
232
- - file: mixin-class-error.rbs
233
- diagnostics:
234
- - range:
235
- start:
236
- line: 5
237
- character: 2
238
- end:
239
- line: 5
240
- character: 13
241
- severity: ERROR
242
- message: Cannot include a class `::Foo` in the definition of `::Bar`
243
- code: RBS::MixinClassError
data/steep.gemspec CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
34
34
  spec.add_runtime_dependency "listen", "~> 3.0"
35
35
  spec.add_runtime_dependency "language_server-protocol", ">= 3.15", "< 4.0"
36
- spec.add_runtime_dependency "rbs", "~> 1.7.0"
36
+ spec.add_runtime_dependency "rbs", ">= 2.2.0"
37
37
  spec.add_runtime_dependency "parallel", ">= 1.0.0"
38
38
  spec.add_runtime_dependency "terminal-table", ">= 2", "< 4"
39
39
  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.47.1
4
+ version: 0.48.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: 2022-02-17 00:00:00.000000000 Z
11
+ date: 2022-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -96,16 +96,16 @@ dependencies:
96
96
  name: rbs
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
- - - "~>"
99
+ - - ">="
100
100
  - !ruby/object:Gem::Version
101
- version: 1.7.0
101
+ version: 2.2.0
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
- - - "~>"
106
+ - - ">="
107
107
  - !ruby/object:Gem::Version
108
- version: 1.7.0
108
+ version: 2.2.0
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: parallel
111
111
  requirement: !ruby/object:Gem::Requirement
@@ -204,7 +204,6 @@ files:
204
204
  - lib/steep/drivers/langserver.rb
205
205
  - lib/steep/drivers/print_project.rb
206
206
  - lib/steep/drivers/stats.rb
207
- - lib/steep/drivers/trace_printer.rb
208
207
  - lib/steep/drivers/utils/driver_helper.rb
209
208
  - lib/steep/drivers/utils/jobs_count.rb
210
209
  - lib/steep/drivers/validate.rb
@@ -219,9 +218,9 @@ files:
219
218
  - lib/steep/interface/block.rb
220
219
  - lib/steep/interface/function.rb
221
220
  - lib/steep/interface/interface.rb
222
- - lib/steep/interface/method.rb
223
221
  - lib/steep/interface/method_type.rb
224
222
  - lib/steep/interface/substitution.rb
223
+ - lib/steep/interface/type_param.rb
225
224
  - lib/steep/method_name.rb
226
225
  - lib/steep/module_helper.rb
227
226
  - lib/steep/project.rb
@@ -247,11 +246,11 @@ files:
247
246
  - lib/steep/services/type_check_service.rb
248
247
  - lib/steep/signature/validator.rb
249
248
  - lib/steep/source.rb
249
+ - lib/steep/subtyping/cache.rb
250
250
  - lib/steep/subtyping/check.rb
251
251
  - lib/steep/subtyping/constraints.rb
252
252
  - lib/steep/subtyping/relation.rb
253
253
  - lib/steep/subtyping/result.rb
254
- - lib/steep/subtyping/trace.rb
255
254
  - lib/steep/subtyping/variable_occurrence.rb
256
255
  - lib/steep/subtyping/variable_variance.rb
257
256
  - lib/steep/type_construction.rb
@@ -271,7 +270,9 @@ files:
271
270
  - manual/annotations.md
272
271
  - sample/Steepfile
273
272
  - sample/lib/conference.rb
273
+ - sample/lib/length.rb
274
274
  - sample/sig/conference.rbs
275
+ - sample/sig/length.rbs
275
276
  - smoke/alias/Steepfile
276
277
  - smoke/alias/a.rb
277
278
  - smoke/alias/a.rbs
@@ -324,8 +325,10 @@ files:
324
325
  - smoke/diagnostics-rbs/invalid-type-application.rbs
325
326
  - smoke/diagnostics-rbs/invalid_variance_annotation.rbs
326
327
  - smoke/diagnostics-rbs/mixin-class-error.rbs
328
+ - smoke/diagnostics-rbs/nonregular-type-alias.rbs
327
329
  - smoke/diagnostics-rbs/recursive-alias.rbs
328
330
  - smoke/diagnostics-rbs/recursive-class.rbs
331
+ - smoke/diagnostics-rbs/recursive-type-alias.rbs
329
332
  - smoke/diagnostics-rbs/superclass-mismatch.rbs
330
333
  - smoke/diagnostics-rbs/test_expectations.yml
331
334
  - smoke/diagnostics-rbs/unknown-method-alias.rbs
@@ -533,7 +536,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
533
536
  - !ruby/object:Gem::Version
534
537
  version: '0'
535
538
  requirements: []
536
- rubygems_version: 3.3.6
539
+ rubygems_version: 3.3.7
537
540
  signing_key:
538
541
  specification_version: 4
539
542
  summary: Gradual Typing for Ruby
@@ -1,29 +0,0 @@
1
- module Steep
2
- module Drivers
3
- class TracePrinter
4
- attr_reader :io
5
-
6
- def initialize(io)
7
- @io = io
8
- end
9
-
10
- def print(trace, level: 0)
11
- trace.each.with_index do |t, i|
12
- prefix = " " * (i + level)
13
- case t[0]
14
- when :type
15
- io.puts "#{prefix}#{t[1]} <: #{t[2]}"
16
- when :method
17
- io.puts "#{prefix}(#{t[3]}) #{t[1]} <: #{t[2]}"
18
- when :method_type
19
- io.puts "#{prefix}#{t[1]} <: #{t[2]}"
20
- when :interface
21
- # nop
22
- else
23
- Steep.logger.error { "Unexpected trace item: #{t[0]}" }
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,78 +0,0 @@
1
- module Steep
2
- module Interface
3
- class Method
4
- attr_reader :type_name
5
- attr_reader :name
6
- attr_reader :super_method
7
- attr_reader :types
8
- attr_reader :attributes
9
-
10
- def initialize(type_name:, name:, types:, super_method:, attributes:)
11
- @type_name = type_name
12
- @name = name
13
- @types = types
14
- @super_method = super_method
15
- @attributes = attributes
16
- end
17
-
18
- def ==(other)
19
- other.is_a?(Method) &&
20
- other.type_name == type_name &&
21
- other.name == name &&
22
- other.types == types &&
23
- other.super_method == super_method &&
24
- other.attributes == attributes
25
- end
26
-
27
- def private?
28
- attributes.include?(:private)
29
- end
30
-
31
- def closed?
32
- types.all?(&:closed?)
33
- end
34
-
35
- def subst(s)
36
- self.class.new(
37
- type_name: type_name,
38
- name: name,
39
- types: types.map {|type| type.subst(s) },
40
- super_method: super_method&.subst(s),
41
- attributes: attributes
42
- )
43
- end
44
-
45
- def with_super(super_method)
46
- self.class.new(
47
- type_name: type_name,
48
- name: name,
49
- types: types,
50
- super_method: super_method,
51
- attributes: attributes
52
- )
53
- end
54
-
55
- def with_types(types)
56
- self.class.new(
57
- type_name: type_name,
58
- name: name,
59
- types: types,
60
- super_method: super_method,
61
- attributes: attributes
62
- )
63
- end
64
-
65
- def map_types
66
- with_types(types.map {|type| yield type })
67
- end
68
-
69
- def include_in_chain?(method)
70
- (method.type_name == type_name &&
71
- method.name == name &&
72
- method.types == types &&
73
- method.attributes == attributes) ||
74
- super_method&.include_in_chain?(method)
75
- end
76
- end
77
- end
78
- end
@@ -1,71 +0,0 @@
1
- module Steep
2
- module Subtyping
3
- class Trace
4
- attr_reader :array
5
-
6
- def initialize(array: [])
7
- @array = array
8
- end
9
-
10
- def interface(sub, sup, &block)
11
- push :interface, sub, sup, &block
12
- end
13
-
14
- def method(name, sub, sup, &block)
15
- push :method, sub, sup, name, &block
16
- end
17
-
18
- def method_type(name, sub, sup, &block)
19
- push :method_type, sub, sup, name, &block
20
- end
21
-
22
- def type(sub, sup, &block)
23
- push :type, sub, sup, &block
24
- end
25
-
26
- def push(*xs)
27
- array << xs
28
- yield
29
- ensure
30
- array.pop
31
- end
32
-
33
- def add(sup, sub)
34
- array << [sup, sub]
35
- yield
36
- ensure
37
- array.pop
38
- end
39
-
40
- def empty?
41
- array.empty?
42
- end
43
-
44
- def drop(n)
45
- self.class.new(array: array.drop(n))
46
- end
47
-
48
- def size
49
- array.size
50
- end
51
-
52
- def +(other)
53
- self.class.new(array: array + other.array)
54
- end
55
-
56
- def initialize_copy(source)
57
- @array = source.array.dup
58
- end
59
-
60
- def each
61
- if block_given?
62
- array.each do |pair|
63
- yield(*pair)
64
- end
65
- else
66
- enum_for :each
67
- end
68
- end
69
- end
70
- end
71
- end