steep 0.47.1 → 0.48.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +6 -6
- data/lib/steep/ast/types/factory.rb +161 -137
- data/lib/steep/ast/types/var.rb +14 -3
- data/lib/steep/diagnostic/ruby.rb +23 -11
- data/lib/steep/diagnostic/signature.rb +56 -0
- data/lib/steep/interface/method_type.rb +14 -26
- data/lib/steep/interface/type_param.rb +103 -0
- data/lib/steep/server/base_worker.rb +1 -0
- data/lib/steep/server/interaction_worker.rb +1 -1
- data/lib/steep/server/type_check_worker.rb +2 -2
- data/lib/steep/services/signature_service.rb +2 -2
- data/lib/steep/services/type_check_service.rb +2 -1
- data/lib/steep/signature/validator.rb +221 -49
- data/lib/steep/subtyping/cache.rb +30 -0
- data/lib/steep/subtyping/check.rb +582 -708
- data/lib/steep/subtyping/constraints.rb +66 -30
- data/lib/steep/subtyping/relation.rb +60 -0
- data/lib/steep/subtyping/result.rb +190 -16
- data/lib/steep/type_construction.rb +492 -371
- data/lib/steep/type_inference/context.rb +37 -3
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +3 -3
- data/sample/lib/length.rb +35 -0
- data/sample/sig/length.rbs +34 -0
- data/smoke/diagnostics-rbs/nonregular-type-alias.rbs +3 -0
- data/smoke/diagnostics-rbs/recursive-type-alias.rbs +3 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +57 -12
- data/steep.gemspec +1 -1
- metadata +13 -10
- data/lib/steep/drivers/trace_printer.rb +0 -29
- data/lib/steep/interface/method.rb +0 -78
- data/lib/steep/subtyping/trace.rb +0 -71
@@ -80,7 +80,7 @@ module Steep
|
|
80
80
|
@vars = Set.new
|
81
81
|
|
82
82
|
unknowns.each do |var|
|
83
|
-
dictionary[var] = [Set.new, Set.new]
|
83
|
+
dictionary[var] = [Set.new, Set.new, Set.new]
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -101,8 +101,8 @@ module Steep
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
def add(var, sub_type: nil, super_type: nil)
|
105
|
-
subs, supers = dictionary[var]
|
104
|
+
def add(var, sub_type: nil, super_type: nil, skip: false)
|
105
|
+
subs, supers, skips = dictionary[var]
|
106
106
|
|
107
107
|
if sub_type.is_a?(AST::Types::Logic::Base)
|
108
108
|
sub_type = AST::Builtin.bool_type
|
@@ -113,11 +113,15 @@ module Steep
|
|
113
113
|
end
|
114
114
|
|
115
115
|
if super_type && !super_type.is_a?(AST::Types::Top)
|
116
|
-
|
116
|
+
type = eliminate_variable(super_type, to: AST::Types::Top.new)
|
117
|
+
supers << type
|
118
|
+
skips << type if skip
|
117
119
|
end
|
118
120
|
|
119
121
|
if sub_type && !sub_type.is_a?(AST::Types::Bot)
|
120
|
-
|
122
|
+
type = eliminate_variable(sub_type, to: AST::Types::Bot.new)
|
123
|
+
subs << type
|
124
|
+
skips << type if skip
|
121
125
|
end
|
122
126
|
|
123
127
|
super_fvs = supers.each.with_object(Set.new) do |type, fvs|
|
@@ -178,12 +182,20 @@ module Steep
|
|
178
182
|
Set.new(dictionary.keys)
|
179
183
|
end
|
180
184
|
|
185
|
+
def unknown!(var)
|
186
|
+
unless unknown?(var)
|
187
|
+
dictionary[var] = [Set.new, Set.new, Set.new]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
181
191
|
def empty?
|
182
192
|
dictionary.keys.empty?
|
183
193
|
end
|
184
194
|
|
185
|
-
def upper_bound(var)
|
186
|
-
_, upper_bound = dictionary[var]
|
195
|
+
def upper_bound(var, skip: false)
|
196
|
+
_, upper_bound, skips = dictionary[var]
|
197
|
+
upper_bound -= skips if skip
|
198
|
+
|
187
199
|
case upper_bound.size
|
188
200
|
when 0
|
189
201
|
AST::Types::Top.new
|
@@ -194,8 +206,9 @@ module Steep
|
|
194
206
|
end
|
195
207
|
end
|
196
208
|
|
197
|
-
def lower_bound(var)
|
198
|
-
lower_bound, _ = dictionary[var]
|
209
|
+
def lower_bound(var, skip: false)
|
210
|
+
lower_bound, _, skips = dictionary[var]
|
211
|
+
lower_bound -= skips if skip
|
199
212
|
|
200
213
|
case lower_bound.size
|
201
214
|
when 0
|
@@ -207,40 +220,61 @@ module Steep
|
|
207
220
|
end
|
208
221
|
end
|
209
222
|
|
210
|
-
|
223
|
+
Context = Struct.new(:variance, :self_type, :instance_type, :class_type, keyword_init: true)
|
224
|
+
|
225
|
+
def solution(checker, variance: nil, variables:, self_type: nil, instance_type: nil, class_type: nil, context: nil)
|
226
|
+
if context
|
227
|
+
raise if variance
|
228
|
+
raise if self_type
|
229
|
+
raise if instance_type
|
230
|
+
raise if class_type
|
231
|
+
|
232
|
+
variance = context.variance
|
233
|
+
self_type = context.self_type
|
234
|
+
instance_type = context.instance_type
|
235
|
+
class_type = context.class_type
|
236
|
+
end
|
237
|
+
|
211
238
|
vars = []
|
212
239
|
types = []
|
213
240
|
|
214
241
|
dictionary.each_key do |var|
|
215
242
|
if variables.include?(var)
|
216
243
|
if has_constraint?(var)
|
217
|
-
|
218
|
-
|
219
|
-
|
244
|
+
relation = Relation.new(
|
245
|
+
sub_type: lower_bound(var, skip: false),
|
246
|
+
super_type: upper_bound(var, skip: false)
|
247
|
+
)
|
220
248
|
|
221
249
|
checker.check(relation, self_type: self_type, instance_type: instance_type, class_type: class_type, constraints: self.class.empty).yield_self do |result|
|
222
250
|
if result.success?
|
223
251
|
vars << var
|
224
252
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
253
|
+
upper_bound = upper_bound(var, skip: true)
|
254
|
+
lower_bound = lower_bound(var, skip: true)
|
255
|
+
|
256
|
+
type =
|
257
|
+
case
|
258
|
+
when variance.contravariant?(var)
|
259
|
+
upper_bound
|
260
|
+
when variance.covariant?(var)
|
261
|
+
lower_bound
|
262
|
+
else
|
263
|
+
if lower_bound.level.join > upper_bound.level.join
|
264
|
+
upper_bound
|
265
|
+
else
|
266
|
+
lower_bound
|
267
|
+
end
|
268
|
+
end
|
237
269
|
|
238
270
|
types << type
|
239
271
|
else
|
240
|
-
raise UnsatisfiableConstraint.new(
|
241
|
-
|
242
|
-
|
243
|
-
|
272
|
+
raise UnsatisfiableConstraint.new(
|
273
|
+
var: var,
|
274
|
+
sub_type: result.relation.sub_type,
|
275
|
+
super_type: result.relation.super_type,
|
276
|
+
result: result
|
277
|
+
)
|
244
278
|
end
|
245
279
|
end
|
246
280
|
else
|
@@ -254,7 +288,9 @@ module Steep
|
|
254
288
|
end
|
255
289
|
|
256
290
|
def has_constraint?(var)
|
257
|
-
lower, upper = dictionary[var]
|
291
|
+
lower, upper, skips = dictionary[var]
|
292
|
+
lower -= skips
|
293
|
+
upper -= skips
|
258
294
|
!lower.empty? || !upper.empty?
|
259
295
|
end
|
260
296
|
|
@@ -23,6 +23,66 @@ module Steep
|
|
23
23
|
"#{sub_type} <: #{super_type}"
|
24
24
|
end
|
25
25
|
|
26
|
+
def to_ary
|
27
|
+
[sub_type, super_type]
|
28
|
+
end
|
29
|
+
|
30
|
+
def type?
|
31
|
+
!interface? && !method? && !function? && !params? && !block?
|
32
|
+
end
|
33
|
+
|
34
|
+
def interface?
|
35
|
+
sub_type.is_a?(Interface::Interface) && super_type.is_a?(Interface::Interface)
|
36
|
+
end
|
37
|
+
|
38
|
+
def method?
|
39
|
+
(sub_type.is_a?(Interface::Interface::Entry) || sub_type.is_a?(Interface::MethodType)) &&
|
40
|
+
(super_type.is_a?(Interface::Interface::Entry) || super_type.is_a?(Interface::MethodType))
|
41
|
+
end
|
42
|
+
|
43
|
+
def function?
|
44
|
+
sub_type.is_a?(Interface::Function) && super_type.is_a?(Interface::Function)
|
45
|
+
end
|
46
|
+
|
47
|
+
def params?
|
48
|
+
sub_type.is_a?(Interface::Function::Params) && super_type.is_a?(Interface::Function::Params)
|
49
|
+
end
|
50
|
+
|
51
|
+
def block?
|
52
|
+
(sub_type.is_a?(Interface::Block) || !sub_type) &&
|
53
|
+
(!super_type || super_type.is_a?(Interface::Block))
|
54
|
+
end
|
55
|
+
|
56
|
+
def assert_type(type)
|
57
|
+
unless __send__(:"#{type}?")
|
58
|
+
raise "#{type}? is expected but: sub_type=#{sub_type.class}, super_type=#{super_type.class}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def type!
|
63
|
+
assert_type(:type)
|
64
|
+
end
|
65
|
+
|
66
|
+
def interface!
|
67
|
+
assert_type(:interface)
|
68
|
+
end
|
69
|
+
|
70
|
+
def method!
|
71
|
+
assert_type(:method)
|
72
|
+
end
|
73
|
+
|
74
|
+
def function!
|
75
|
+
assert_type(:function)
|
76
|
+
end
|
77
|
+
|
78
|
+
def params!
|
79
|
+
assert_type(:params)
|
80
|
+
end
|
81
|
+
|
82
|
+
def block!
|
83
|
+
assert_type(:block)
|
84
|
+
end
|
85
|
+
|
26
86
|
def map
|
27
87
|
self.class.new(
|
28
88
|
sub_type: yield(sub_type),
|
@@ -2,6 +2,12 @@ module Steep
|
|
2
2
|
module Subtyping
|
3
3
|
module Result
|
4
4
|
class Base
|
5
|
+
attr_reader :relation
|
6
|
+
|
7
|
+
def initialize(relation)
|
8
|
+
@relation = relation
|
9
|
+
end
|
10
|
+
|
5
11
|
def failure?
|
6
12
|
!success?
|
7
13
|
end
|
@@ -21,18 +27,139 @@ module Steep
|
|
21
27
|
self
|
22
28
|
end
|
23
29
|
end
|
30
|
+
|
31
|
+
def failure_path(path = [])
|
32
|
+
raise
|
33
|
+
end
|
24
34
|
end
|
25
35
|
|
26
|
-
class
|
27
|
-
|
36
|
+
class Skip < Base
|
37
|
+
def success?
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def failure_path(path = [])
|
46
|
+
raise
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Expand < Base
|
51
|
+
attr_reader :child
|
52
|
+
|
53
|
+
def initialize(relation, &block)
|
54
|
+
super relation
|
55
|
+
@child = yield relation
|
56
|
+
|
57
|
+
raise if @child == true
|
58
|
+
end
|
59
|
+
|
60
|
+
def success?
|
61
|
+
child.success?
|
62
|
+
end
|
28
63
|
|
29
|
-
def
|
30
|
-
|
64
|
+
def failure_path(path = [])
|
65
|
+
if child.failure?
|
66
|
+
path.unshift(self)
|
67
|
+
child.failure_path(path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class All < Base
|
73
|
+
attr_reader :branches
|
74
|
+
|
75
|
+
def initialize(relation)
|
76
|
+
super relation
|
77
|
+
@branches = []
|
78
|
+
@failure = false
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns `false` if no future `#add` changes the result.
|
82
|
+
def add(*relations, &block)
|
83
|
+
relations.each do |relation|
|
84
|
+
if success?
|
85
|
+
result = yield(relation)
|
86
|
+
branches << result
|
87
|
+
else
|
88
|
+
# Already failed.
|
89
|
+
branches << Skip.new(relation)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# No need to test more branches if already failed.
|
94
|
+
success?
|
31
95
|
end
|
32
96
|
|
97
|
+
def success?
|
98
|
+
!failure?
|
99
|
+
end
|
100
|
+
|
101
|
+
def failure?
|
102
|
+
@failure ||= branches.any?(&:failure?)
|
103
|
+
end
|
104
|
+
|
105
|
+
def failure_path(path = [])
|
106
|
+
if failure?
|
107
|
+
r = branches.find(&:failure?)
|
108
|
+
path.unshift(self)
|
109
|
+
r.failure_path(path)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class Any < Base
|
115
|
+
attr_reader :branches
|
116
|
+
|
117
|
+
def initialize(relation)
|
118
|
+
super relation
|
119
|
+
@branches = []
|
120
|
+
@success = false
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns `false` if no future `#add` changes the result.
|
124
|
+
def add(*relations, &block)
|
125
|
+
relations.each do |relation|
|
126
|
+
if failure?
|
127
|
+
result = yield(relation)
|
128
|
+
branches << result
|
129
|
+
else
|
130
|
+
# Already succeeded.
|
131
|
+
branches << Skip.new(relation)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# No need to test more branches if already succeeded.
|
136
|
+
failure?
|
137
|
+
end
|
138
|
+
|
139
|
+
def success?
|
140
|
+
@success ||= branches.any?(&:success?)
|
141
|
+
end
|
142
|
+
|
143
|
+
def failure_path(path = [])
|
144
|
+
if failure?
|
145
|
+
path.unshift(self)
|
146
|
+
if r = branches.find(&:failure?)
|
147
|
+
r.failure_path(path)
|
148
|
+
else
|
149
|
+
path
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class Success < Base
|
33
156
|
def success?
|
34
157
|
true
|
35
158
|
end
|
159
|
+
|
160
|
+
def failure_path(path = [])
|
161
|
+
nil
|
162
|
+
end
|
36
163
|
end
|
37
164
|
|
38
165
|
class Failure < Base
|
@@ -96,29 +223,76 @@ module Steep
|
|
96
223
|
end
|
97
224
|
end
|
98
225
|
|
226
|
+
class UnsatisfiedConstraints
|
227
|
+
attr_reader :error
|
228
|
+
|
229
|
+
def initialize(error)
|
230
|
+
@error = error
|
231
|
+
end
|
232
|
+
|
233
|
+
def var
|
234
|
+
error.var
|
235
|
+
end
|
236
|
+
|
237
|
+
def sub_type
|
238
|
+
error.sub_type
|
239
|
+
end
|
240
|
+
|
241
|
+
def super_type
|
242
|
+
error.super_type
|
243
|
+
end
|
244
|
+
|
245
|
+
def result
|
246
|
+
error.result
|
247
|
+
end
|
248
|
+
|
249
|
+
def message
|
250
|
+
"A constraint on #{var} cannot be solved: #{sub_type} <: #{super_type}"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
99
254
|
attr_reader :error
|
100
|
-
attr_reader :trace
|
101
255
|
|
102
|
-
def initialize(error
|
256
|
+
def initialize(relation, error)
|
257
|
+
super relation
|
103
258
|
@error = error
|
104
|
-
@trace = trace.dup
|
105
259
|
end
|
106
260
|
|
107
261
|
def success?
|
108
262
|
false
|
109
263
|
end
|
110
264
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
265
|
+
def failure_path(path = [])
|
266
|
+
path.unshift(self)
|
267
|
+
path
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
module Helper
|
272
|
+
def Skip(relation)
|
273
|
+
Skip.new(relation)
|
274
|
+
end
|
275
|
+
|
276
|
+
def Expand(relation, &block)
|
277
|
+
Expand.new(relation, &block)
|
278
|
+
end
|
279
|
+
|
280
|
+
def All(relation, &block)
|
281
|
+
All.new(relation).tap(&block)
|
118
282
|
end
|
119
283
|
|
120
|
-
def
|
121
|
-
|
284
|
+
def Any(relation, &block)
|
285
|
+
Any.new(relation).tap(&block)
|
286
|
+
end
|
287
|
+
|
288
|
+
def Success(relation)
|
289
|
+
Success.new(relation)
|
290
|
+
end
|
291
|
+
|
292
|
+
alias success Success
|
293
|
+
|
294
|
+
def Failure(relation, error = nil)
|
295
|
+
Failure.new(relation, error || yield)
|
122
296
|
end
|
123
297
|
end
|
124
298
|
end
|