steep 0.47.1 → 0.49.1
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 +24 -0
- data/Gemfile.lock +7 -7
- 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 +36 -11
- data/lib/steep/diagnostic/signature.rb +56 -0
- data/lib/steep/drivers/check.rb +2 -2
- 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 +4 -1
- data/lib/steep/signature/validator.rb +228 -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 +576 -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 +3 -3
- data/sample/lib/length.rb +35 -0
- data/sample/sig/length.rbs +34 -0
- data/smoke/diagnostics/proc_type_expected.rb +3 -0
- data/smoke/diagnostics/test_expectations.yml +12 -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 +14 -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,80 @@ 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
|
+
|
92
|
+
def validate_type_application(type)
|
93
|
+
name, type_params, type_args =
|
94
|
+
case type
|
95
|
+
when RBS::Types::ClassInstance
|
96
|
+
[
|
97
|
+
type.name,
|
98
|
+
builder.build_instance(type.name).type_params_decl,
|
99
|
+
type.args
|
100
|
+
]
|
101
|
+
when RBS::Types::Interface
|
102
|
+
[
|
103
|
+
type.name,
|
104
|
+
builder.build_interface(type.name).type_params_decl,
|
105
|
+
type.args
|
106
|
+
]
|
107
|
+
when RBS::Types::Alias
|
108
|
+
entry = env.alias_decls[type.name]
|
109
|
+
|
110
|
+
[
|
111
|
+
type.name,
|
112
|
+
entry.decl.type_params,
|
113
|
+
type.args
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
if name && type_params && type_args
|
118
|
+
if !type_params.empty? && !type_args.empty?
|
119
|
+
validate_type_application_constraints(type.name, type_params, type_args, location: type.location)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
type.each_type do |child|
|
124
|
+
validate_type_application(child)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
59
128
|
def validate_type(type)
|
60
129
|
Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
|
130
|
+
|
61
131
|
validator.validate_type type, context: [RBS::Namespace.root]
|
132
|
+
validate_type_application(type)
|
62
133
|
end
|
63
134
|
|
64
135
|
def ancestor_to_type(ancestor)
|
@@ -109,64 +180,109 @@ module Steep
|
|
109
180
|
relations
|
110
181
|
end
|
111
182
|
|
183
|
+
def each_method_type(definition)
|
184
|
+
type_name = definition.type_name
|
185
|
+
|
186
|
+
definition.methods.each_value do |method|
|
187
|
+
if method.defined_in == type_name
|
188
|
+
method.method_types.each do |method_type|
|
189
|
+
yield method_type
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def each_variable_type(definition)
|
196
|
+
type_name = definition.type_name
|
197
|
+
|
198
|
+
definition.instance_variables.each_value do |var|
|
199
|
+
if var.declared_in == type_name
|
200
|
+
yield var.type
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
definition.class_variables.each_value do |var|
|
205
|
+
if var.declared_in == type_name
|
206
|
+
yield var.type
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def validate_definition_type(definition)
|
212
|
+
each_method_type(definition) do |method_type|
|
213
|
+
upper_bounds = method_type.type_params.each.with_object({}) do |param, hash|
|
214
|
+
hash[param.name] = factory.type_opt(param.upper_bound)
|
215
|
+
end
|
216
|
+
|
217
|
+
checker.push_variable_bounds(upper_bounds) do
|
218
|
+
method_type.each_type do |type|
|
219
|
+
validate_type(type)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
each_variable_type(definition) do |type|
|
225
|
+
validate_type(type)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
112
229
|
def validate_one_class(name)
|
113
230
|
rescue_validation_errors(name) do
|
114
231
|
Steep.logger.debug { "Validating class definition `#{name}`..." }
|
115
232
|
|
116
233
|
Steep.logger.tagged "#{name}" do
|
117
234
|
builder.build_instance(name).tap do |definition|
|
118
|
-
definition.
|
119
|
-
|
120
|
-
|
121
|
-
parent_type = checker.factory.type(parent.type)
|
235
|
+
upper_bounds = definition.type_params_decl.each.with_object({}) do |param, bounds|
|
236
|
+
bounds[param.name] = factory.type_opt(param.upper_bound)
|
237
|
+
end
|
122
238
|
|
123
|
-
|
124
|
-
|
239
|
+
checker.push_variable_bounds(upper_bounds) do
|
240
|
+
definition.instance_variables.each do |name, var|
|
241
|
+
if parent = var.parent_variable
|
242
|
+
var_type = checker.factory.type(var.type)
|
243
|
+
parent_type = checker.factory.type(parent.type)
|
244
|
+
|
245
|
+
relation = Subtyping::Relation.new(sub_type: var_type, super_type: parent_type)
|
246
|
+
result1 = checker.check(relation, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
|
247
|
+
result2 = checker.check(relation.flip, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
|
248
|
+
|
249
|
+
unless result1.success? and result2.success?
|
250
|
+
@errors << Diagnostic::Signature::InstanceVariableTypeError.new(
|
251
|
+
name: name,
|
252
|
+
location: var.type.location,
|
253
|
+
var_type: var_type,
|
254
|
+
parent_type: parent_type
|
255
|
+
)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
ancestors = builder.ancestor_builder.one_instance_ancestors(name)
|
261
|
+
mixin_constraints(definition, ancestors.included_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
|
262
|
+
checker.check(
|
125
263
|
relation,
|
126
264
|
self_type: AST::Types::Self.new,
|
127
265
|
instance_type: AST::Types::Instance.new,
|
128
266
|
class_type: AST::Types::Class.new,
|
129
267
|
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(
|
268
|
+
).else do
|
269
|
+
@errors << Diagnostic::Signature::ModuleSelfTypeError.new(
|
141
270
|
name: name,
|
142
|
-
location:
|
143
|
-
|
144
|
-
|
271
|
+
location: ancestor.source&.location || raise,
|
272
|
+
ancestor: ancestor,
|
273
|
+
relation: relation
|
145
274
|
)
|
146
275
|
end
|
147
276
|
end
|
148
|
-
end
|
149
277
|
|
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
|
-
)
|
278
|
+
ancestors.each_ancestor do |ancestor|
|
279
|
+
case ancestor
|
280
|
+
when RBS::Definition::Ancestor::Instance
|
281
|
+
validate_ancestor_application(name, ancestor)
|
282
|
+
end
|
165
283
|
end
|
166
|
-
end
|
167
284
|
|
168
|
-
|
169
|
-
validate_type type
|
285
|
+
validate_definition_type(definition)
|
170
286
|
end
|
171
287
|
end
|
172
288
|
|
@@ -220,21 +336,78 @@ module Steep
|
|
220
336
|
)
|
221
337
|
end
|
222
338
|
end
|
223
|
-
|
224
|
-
|
225
|
-
|
339
|
+
ancestors.each_ancestor do |ancestor|
|
340
|
+
case ancestor
|
341
|
+
when RBS::Definition::Ancestor::Instance
|
342
|
+
validate_ancestor_application(name, ancestor)
|
343
|
+
end
|
226
344
|
end
|
345
|
+
|
346
|
+
validate_definition_type(definition)
|
227
347
|
end
|
228
348
|
end
|
229
349
|
end
|
230
350
|
end
|
231
351
|
|
352
|
+
def validate_ancestor_application(name, ancestor)
|
353
|
+
unless ancestor.args.empty?
|
354
|
+
definition =
|
355
|
+
case
|
356
|
+
when ancestor.name.class?
|
357
|
+
builder.build_instance(ancestor.name)
|
358
|
+
when ancestor.name.interface?
|
359
|
+
builder.build_interface(ancestor.name)
|
360
|
+
end
|
361
|
+
|
362
|
+
location =
|
363
|
+
if ancestor.source == :super
|
364
|
+
primary_decl = env.class_decls[name].primary.decl
|
365
|
+
if super_class = primary_decl.super_class
|
366
|
+
super_class.location
|
367
|
+
else
|
368
|
+
# Implicit super class (Object): this can be skipped in fact...
|
369
|
+
primary_decl.location[:name]
|
370
|
+
end
|
371
|
+
else
|
372
|
+
ancestor.source.location
|
373
|
+
end
|
374
|
+
|
375
|
+
validate_type_application_constraints(
|
376
|
+
ancestor.name,
|
377
|
+
definition.type_params_decl,
|
378
|
+
ancestor.args,
|
379
|
+
location: location
|
380
|
+
)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
232
384
|
def validate_one_interface(name)
|
233
385
|
rescue_validation_errors(name) do
|
234
386
|
Steep.logger.debug "Validating interface `#{name}`..."
|
235
387
|
Steep.logger.tagged "#{name}" do
|
236
|
-
builder.build_interface(name)
|
237
|
-
|
388
|
+
definition = builder.build_interface(name)
|
389
|
+
|
390
|
+
upper_bounds = definition.type_params_decl.each.with_object({}) do |param, bounds|
|
391
|
+
bounds[param.name] = factory.type_opt(param.upper_bound)
|
392
|
+
end
|
393
|
+
|
394
|
+
checker.push_variable_bounds(upper_bounds) do
|
395
|
+
validate_definition_type(definition)
|
396
|
+
|
397
|
+
ancestors = builder.ancestor_builder.one_interface_ancestors(name)
|
398
|
+
ancestors.each_ancestor do |ancestor|
|
399
|
+
case ancestor
|
400
|
+
when RBS::Definition::Ancestor::Instance
|
401
|
+
# Interface ancestor cannot be other than Interface
|
402
|
+
defn = builder.build_interface(ancestor.name)
|
403
|
+
validate_type_application_constraints(
|
404
|
+
ancestor.name,
|
405
|
+
defn.type_params_decl,
|
406
|
+
ancestor.args,
|
407
|
+
location: ancestor.source.location || raise
|
408
|
+
)
|
409
|
+
end
|
410
|
+
end
|
238
411
|
end
|
239
412
|
end
|
240
413
|
end
|
@@ -277,24 +450,30 @@ module Steep
|
|
277
450
|
end
|
278
451
|
end
|
279
452
|
|
280
|
-
def validate_one_alias(name)
|
453
|
+
def validate_one_alias(name, entry = env.alias_decls[name])
|
281
454
|
rescue_validation_errors(name) do
|
282
455
|
Steep.logger.debug "Validating alias `#{name}`..."
|
283
|
-
|
284
|
-
|
456
|
+
upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
|
457
|
+
bounds[param.name] = factory.type_opt(param.upper_bound)
|
458
|
+
end
|
459
|
+
|
460
|
+
validator.validate_type_alias(entry: entry) do |type|
|
461
|
+
checker.push_variable_bounds(upper_bounds) do
|
462
|
+
validate_type(entry.decl.type)
|
463
|
+
end
|
285
464
|
end
|
286
465
|
end
|
287
466
|
end
|
288
467
|
|
289
468
|
def validate_alias
|
290
469
|
env.alias_decls.each do |name, entry|
|
291
|
-
validate_one_alias(name)
|
470
|
+
validate_one_alias(name, entry)
|
292
471
|
end
|
293
472
|
end
|
294
473
|
|
295
474
|
def rescue_validation_errors(type_name = nil)
|
296
475
|
yield
|
297
|
-
rescue RBS::
|
476
|
+
rescue RBS::BaseError => exn
|
298
477
|
@errors << Diagnostic::Signature.from_rbs_error(exn, factory: factory)
|
299
478
|
end
|
300
479
|
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
|