steep 0.47.0 → 0.49.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +14 -16
- data/lib/steep/ast/types/any.rb +2 -0
- data/lib/steep/ast/types/boolean.rb +2 -0
- data/lib/steep/ast/types/bot.rb +2 -0
- data/lib/steep/ast/types/class.rb +2 -0
- data/lib/steep/ast/types/factory.rb +162 -138
- data/lib/steep/ast/types/helper.rb +8 -0
- data/lib/steep/ast/types/instance.rb +2 -0
- data/lib/steep/ast/types/intersection.rb +4 -0
- data/lib/steep/ast/types/literal.rb +2 -0
- data/lib/steep/ast/types/logic.rb +2 -0
- data/lib/steep/ast/types/name.rb +6 -0
- data/lib/steep/ast/types/nil.rb +2 -0
- data/lib/steep/ast/types/proc.rb +9 -0
- data/lib/steep/ast/types/record.rb +4 -0
- data/lib/steep/ast/types/self.rb +2 -0
- data/lib/steep/ast/types/top.rb +2 -0
- data/lib/steep/ast/types/tuple.rb +4 -0
- data/lib/steep/ast/types/union.rb +4 -0
- data/lib/steep/ast/types/var.rb +16 -3
- data/lib/steep/ast/types/void.rb +2 -0
- data/lib/steep/diagnostic/ruby.rb +23 -11
- data/lib/steep/diagnostic/signature.rb +56 -0
- data/lib/steep/interface/function.rb +4 -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 +600 -705
- 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 +543 -395
- data/lib/steep/type_inference/block_params.rb +31 -3
- data/lib/steep/type_inference/context.rb +37 -3
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +4 -4
- 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/smoke/tsort/a.rb +1 -1
- data/smoke/tsort/test_expectations.yml +1 -63
- 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
@@ -56,9 +56,73 @@ module Steep
|
|
56
56
|
validate_alias
|
57
57
|
end
|
58
58
|
|
59
|
+
def validate_type_application_constraints(type_name, type_params, type_args, location:)
|
60
|
+
if type_params.size == type_args.size
|
61
|
+
type_params.zip(type_args).each do |param, arg|
|
62
|
+
if param.upper_bound
|
63
|
+
upper_bound_type = factory.type(param.upper_bound)
|
64
|
+
arg_type = factory.type(arg)
|
65
|
+
|
66
|
+
constraints = Subtyping::Constraints.empty
|
67
|
+
|
68
|
+
checker.check(
|
69
|
+
Subtyping::Relation.new(sub_type: arg_type, super_type: upper_bound_type),
|
70
|
+
self_type: nil,
|
71
|
+
class_type: nil,
|
72
|
+
instance_type: nil,
|
73
|
+
constraints: constraints
|
74
|
+
).else do |result|
|
75
|
+
@errors << Diagnostic::Signature::UnsatisfiableTypeApplication.new(
|
76
|
+
type_name: type_name,
|
77
|
+
type_arg: arg_type,
|
78
|
+
type_param: Interface::TypeParam.new(
|
79
|
+
name: param.name,
|
80
|
+
upper_bound: upper_bound_type,
|
81
|
+
variance: param.variance,
|
82
|
+
unchecked: param.unchecked?
|
83
|
+
),
|
84
|
+
location: location
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
59
92
|
def validate_type(type)
|
60
93
|
Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
|
94
|
+
|
61
95
|
validator.validate_type type, context: [RBS::Namespace.root]
|
96
|
+
|
97
|
+
name, type_params, type_args =
|
98
|
+
case type
|
99
|
+
when RBS::Types::ClassInstance
|
100
|
+
[
|
101
|
+
type.name,
|
102
|
+
builder.build_instance(type.name).type_params_decl,
|
103
|
+
type.args
|
104
|
+
]
|
105
|
+
when RBS::Types::Interface
|
106
|
+
[
|
107
|
+
type.name,
|
108
|
+
builder.build_interface(type.name).type_params_decl,
|
109
|
+
type.args
|
110
|
+
]
|
111
|
+
when RBS::Types::Alias
|
112
|
+
entry = env.alias_decls[type.name]
|
113
|
+
|
114
|
+
[
|
115
|
+
type.name,
|
116
|
+
entry.decl.type_params,
|
117
|
+
type.args
|
118
|
+
]
|
119
|
+
end
|
120
|
+
|
121
|
+
if name && type_params && type_args
|
122
|
+
if !type_params.empty? && !type_args.empty?
|
123
|
+
validate_type_application_constraints(type.name, type_params, type_args, location: type.location)
|
124
|
+
end
|
125
|
+
end
|
62
126
|
end
|
63
127
|
|
64
128
|
def ancestor_to_type(ancestor)
|
@@ -109,64 +173,109 @@ module Steep
|
|
109
173
|
relations
|
110
174
|
end
|
111
175
|
|
176
|
+
def each_method_type(definition)
|
177
|
+
type_name = definition.type_name
|
178
|
+
|
179
|
+
definition.methods.each_value do |method|
|
180
|
+
if method.defined_in == type_name
|
181
|
+
method.method_types.each do |method_type|
|
182
|
+
yield method_type
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def each_variable_type(definition)
|
189
|
+
type_name = definition.type_name
|
190
|
+
|
191
|
+
definition.instance_variables.each_value do |var|
|
192
|
+
if var.declared_in == type_name
|
193
|
+
yield var.type
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
definition.class_variables.each_value do |var|
|
198
|
+
if var.declared_in == type_name
|
199
|
+
yield var.type
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def validate_definition_type(definition)
|
205
|
+
each_method_type(definition) do |method_type|
|
206
|
+
upper_bounds = method_type.type_params.each.with_object({}) do |param, hash|
|
207
|
+
hash[param.name] = factory.type_opt(param.upper_bound)
|
208
|
+
end
|
209
|
+
|
210
|
+
checker.push_variable_bounds(upper_bounds) do
|
211
|
+
method_type.each_type do |type|
|
212
|
+
validate_type(type)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
each_variable_type(definition) do |type|
|
218
|
+
validate_type(type)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
112
222
|
def validate_one_class(name)
|
113
223
|
rescue_validation_errors(name) do
|
114
224
|
Steep.logger.debug { "Validating class definition `#{name}`..." }
|
115
225
|
|
116
226
|
Steep.logger.tagged "#{name}" do
|
117
227
|
builder.build_instance(name).tap do |definition|
|
118
|
-
definition.
|
119
|
-
|
120
|
-
|
121
|
-
parent_type = checker.factory.type(parent.type)
|
228
|
+
upper_bounds = definition.type_params_decl.each.with_object({}) do |param, bounds|
|
229
|
+
bounds[param.name] = factory.type_opt(param.upper_bound)
|
230
|
+
end
|
122
231
|
|
123
|
-
|
124
|
-
|
232
|
+
checker.push_variable_bounds(upper_bounds) do
|
233
|
+
definition.instance_variables.each do |name, var|
|
234
|
+
if parent = var.parent_variable
|
235
|
+
var_type = checker.factory.type(var.type)
|
236
|
+
parent_type = checker.factory.type(parent.type)
|
237
|
+
|
238
|
+
relation = Subtyping::Relation.new(sub_type: var_type, super_type: parent_type)
|
239
|
+
result1 = checker.check(relation, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
|
240
|
+
result2 = checker.check(relation.flip, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
|
241
|
+
|
242
|
+
unless result1.success? and result2.success?
|
243
|
+
@errors << Diagnostic::Signature::InstanceVariableTypeError.new(
|
244
|
+
name: name,
|
245
|
+
location: var.type.location,
|
246
|
+
var_type: var_type,
|
247
|
+
parent_type: parent_type
|
248
|
+
)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
ancestors = builder.ancestor_builder.one_instance_ancestors(name)
|
254
|
+
mixin_constraints(definition, ancestors.included_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
|
255
|
+
checker.check(
|
125
256
|
relation,
|
126
257
|
self_type: AST::Types::Self.new,
|
127
258
|
instance_type: AST::Types::Instance.new,
|
128
259
|
class_type: AST::Types::Class.new,
|
129
260
|
constraints: Subtyping::Constraints.empty
|
130
|
-
)
|
131
|
-
|
132
|
-
relation.flip,
|
133
|
-
self_type: AST::Types::Self.new,
|
134
|
-
instance_type: AST::Types::Instance.new,
|
135
|
-
class_type: AST::Types::Class.new,
|
136
|
-
constraints: Subtyping::Constraints.empty
|
137
|
-
)
|
138
|
-
|
139
|
-
unless result1.success? and result2.success?
|
140
|
-
@errors << Diagnostic::Signature::InstanceVariableTypeError.new(
|
261
|
+
).else do
|
262
|
+
@errors << Diagnostic::Signature::ModuleSelfTypeError.new(
|
141
263
|
name: name,
|
142
|
-
location:
|
143
|
-
|
144
|
-
|
264
|
+
location: ancestor.source&.location || raise,
|
265
|
+
ancestor: ancestor,
|
266
|
+
relation: relation
|
145
267
|
)
|
146
268
|
end
|
147
269
|
end
|
148
|
-
end
|
149
270
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
instance_type: AST::Types::Instance.new,
|
156
|
-
class_type: AST::Types::Class.new,
|
157
|
-
constraints: Subtyping::Constraints.empty
|
158
|
-
).else do
|
159
|
-
@errors << Diagnostic::Signature::ModuleSelfTypeError.new(
|
160
|
-
name: name,
|
161
|
-
location: ancestor.source&.location || raise,
|
162
|
-
ancestor: ancestor,
|
163
|
-
relation: relation
|
164
|
-
)
|
271
|
+
ancestors.each_ancestor do |ancestor|
|
272
|
+
case ancestor
|
273
|
+
when RBS::Definition::Ancestor::Instance
|
274
|
+
validate_ancestor_application(name, ancestor)
|
275
|
+
end
|
165
276
|
end
|
166
|
-
end
|
167
277
|
|
168
|
-
|
169
|
-
validate_type type
|
278
|
+
validate_definition_type(definition)
|
170
279
|
end
|
171
280
|
end
|
172
281
|
|
@@ -220,21 +329,78 @@ module Steep
|
|
220
329
|
)
|
221
330
|
end
|
222
331
|
end
|
223
|
-
|
224
|
-
|
225
|
-
|
332
|
+
ancestors.each_ancestor do |ancestor|
|
333
|
+
case ancestor
|
334
|
+
when RBS::Definition::Ancestor::Instance
|
335
|
+
validate_ancestor_application(name, ancestor)
|
336
|
+
end
|
226
337
|
end
|
338
|
+
|
339
|
+
validate_definition_type(definition)
|
227
340
|
end
|
228
341
|
end
|
229
342
|
end
|
230
343
|
end
|
231
344
|
|
345
|
+
def validate_ancestor_application(name, ancestor)
|
346
|
+
unless ancestor.args.empty?
|
347
|
+
definition =
|
348
|
+
case
|
349
|
+
when ancestor.name.class?
|
350
|
+
builder.build_instance(ancestor.name)
|
351
|
+
when ancestor.name.interface?
|
352
|
+
builder.build_interface(ancestor.name)
|
353
|
+
end
|
354
|
+
|
355
|
+
location =
|
356
|
+
if ancestor.source == :super
|
357
|
+
primary_decl = env.class_decls[name].primary.decl
|
358
|
+
if super_class = primary_decl.super_class
|
359
|
+
super_class.location
|
360
|
+
else
|
361
|
+
# Implicit super class (Object): this can be skipped in fact...
|
362
|
+
primary_decl.location[:name]
|
363
|
+
end
|
364
|
+
else
|
365
|
+
ancestor.source.location
|
366
|
+
end
|
367
|
+
|
368
|
+
validate_type_application_constraints(
|
369
|
+
ancestor.name,
|
370
|
+
definition.type_params_decl,
|
371
|
+
ancestor.args,
|
372
|
+
location: location
|
373
|
+
)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
232
377
|
def validate_one_interface(name)
|
233
378
|
rescue_validation_errors(name) do
|
234
379
|
Steep.logger.debug "Validating interface `#{name}`..."
|
235
380
|
Steep.logger.tagged "#{name}" do
|
236
|
-
builder.build_interface(name)
|
237
|
-
|
381
|
+
definition = builder.build_interface(name)
|
382
|
+
|
383
|
+
upper_bounds = definition.type_params_decl.each.with_object({}) do |param, bounds|
|
384
|
+
bounds[param.name] = factory.type_opt(param.upper_bound)
|
385
|
+
end
|
386
|
+
|
387
|
+
checker.push_variable_bounds(upper_bounds) do
|
388
|
+
validate_definition_type(definition)
|
389
|
+
|
390
|
+
ancestors = builder.ancestor_builder.one_interface_ancestors(name)
|
391
|
+
ancestors.each_ancestor do |ancestor|
|
392
|
+
case ancestor
|
393
|
+
when RBS::Definition::Ancestor::Instance
|
394
|
+
# Interface ancestor cannot be other than Interface
|
395
|
+
defn = builder.build_interface(ancestor.name)
|
396
|
+
validate_type_application_constraints(
|
397
|
+
ancestor.name,
|
398
|
+
defn.type_params_decl,
|
399
|
+
ancestor.args,
|
400
|
+
location: ancestor.source.location || raise
|
401
|
+
)
|
402
|
+
end
|
403
|
+
end
|
238
404
|
end
|
239
405
|
end
|
240
406
|
end
|
@@ -277,24 +443,30 @@ module Steep
|
|
277
443
|
end
|
278
444
|
end
|
279
445
|
|
280
|
-
def validate_one_alias(name)
|
446
|
+
def validate_one_alias(name, entry = env.alias_decls[name])
|
281
447
|
rescue_validation_errors(name) do
|
282
448
|
Steep.logger.debug "Validating alias `#{name}`..."
|
283
|
-
|
284
|
-
|
449
|
+
upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
|
450
|
+
bounds[param.name] = factory.type_opt(param.upper_bound)
|
451
|
+
end
|
452
|
+
|
453
|
+
validator.validate_type_alias(entry: entry) do |type|
|
454
|
+
checker.push_variable_bounds(upper_bounds) do
|
455
|
+
validate_type(entry.decl.type)
|
456
|
+
end
|
285
457
|
end
|
286
458
|
end
|
287
459
|
end
|
288
460
|
|
289
461
|
def validate_alias
|
290
462
|
env.alias_decls.each do |name, entry|
|
291
|
-
validate_one_alias(name)
|
463
|
+
validate_one_alias(name, entry)
|
292
464
|
end
|
293
465
|
end
|
294
466
|
|
295
467
|
def rescue_validation_errors(type_name = nil)
|
296
468
|
yield
|
297
|
-
rescue RBS::
|
469
|
+
rescue RBS::BaseError => exn
|
298
470
|
@errors << Diagnostic::Signature.from_rbs_error(exn, factory: factory)
|
299
471
|
end
|
300
472
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Steep
|
2
|
+
module Subtyping
|
3
|
+
class Cache
|
4
|
+
attr_reader :subtypes
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@subtypes = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def subtype(relation, self_type, instance_type, class_type, bounds)
|
11
|
+
key = [relation, self_type, instance_type, class_type, bounds]
|
12
|
+
subtypes[key]
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](relation, self_type, instance_type, class_type, bounds)
|
16
|
+
key = [relation, self_type, instance_type, class_type, bounds]
|
17
|
+
subtypes[key]
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(relation, self_type, instance_type, class_type, bounds, value)
|
21
|
+
key = [relation, self_type, instance_type, class_type, bounds]
|
22
|
+
subtypes[key] = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def no_subtype_cache?
|
26
|
+
@subtypes.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|