steep 0.47.0 → 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +14 -16
  5. data/lib/steep/ast/types/any.rb +2 -0
  6. data/lib/steep/ast/types/boolean.rb +2 -0
  7. data/lib/steep/ast/types/bot.rb +2 -0
  8. data/lib/steep/ast/types/class.rb +2 -0
  9. data/lib/steep/ast/types/factory.rb +162 -138
  10. data/lib/steep/ast/types/helper.rb +8 -0
  11. data/lib/steep/ast/types/instance.rb +2 -0
  12. data/lib/steep/ast/types/intersection.rb +4 -0
  13. data/lib/steep/ast/types/literal.rb +2 -0
  14. data/lib/steep/ast/types/logic.rb +2 -0
  15. data/lib/steep/ast/types/name.rb +6 -0
  16. data/lib/steep/ast/types/nil.rb +2 -0
  17. data/lib/steep/ast/types/proc.rb +9 -0
  18. data/lib/steep/ast/types/record.rb +4 -0
  19. data/lib/steep/ast/types/self.rb +2 -0
  20. data/lib/steep/ast/types/top.rb +2 -0
  21. data/lib/steep/ast/types/tuple.rb +4 -0
  22. data/lib/steep/ast/types/union.rb +4 -0
  23. data/lib/steep/ast/types/var.rb +16 -3
  24. data/lib/steep/ast/types/void.rb +2 -0
  25. data/lib/steep/diagnostic/ruby.rb +23 -11
  26. data/lib/steep/diagnostic/signature.rb +56 -0
  27. data/lib/steep/interface/function.rb +4 -0
  28. data/lib/steep/interface/method_type.rb +14 -26
  29. data/lib/steep/interface/type_param.rb +103 -0
  30. data/lib/steep/server/base_worker.rb +1 -0
  31. data/lib/steep/server/interaction_worker.rb +1 -1
  32. data/lib/steep/server/type_check_worker.rb +2 -2
  33. data/lib/steep/services/signature_service.rb +2 -2
  34. data/lib/steep/services/type_check_service.rb +2 -1
  35. data/lib/steep/signature/validator.rb +221 -49
  36. data/lib/steep/subtyping/cache.rb +30 -0
  37. data/lib/steep/subtyping/check.rb +600 -705
  38. data/lib/steep/subtyping/constraints.rb +66 -30
  39. data/lib/steep/subtyping/relation.rb +60 -0
  40. data/lib/steep/subtyping/result.rb +190 -16
  41. data/lib/steep/type_construction.rb +543 -395
  42. data/lib/steep/type_inference/block_params.rb +31 -3
  43. data/lib/steep/type_inference/context.rb +37 -3
  44. data/lib/steep/version.rb +1 -1
  45. data/lib/steep.rb +4 -4
  46. data/sample/lib/length.rb +35 -0
  47. data/sample/sig/length.rbs +34 -0
  48. data/smoke/diagnostics-rbs/nonregular-type-alias.rbs +3 -0
  49. data/smoke/diagnostics-rbs/recursive-type-alias.rbs +3 -0
  50. data/smoke/diagnostics-rbs/test_expectations.yml +57 -12
  51. data/smoke/tsort/a.rb +1 -1
  52. data/smoke/tsort/test_expectations.yml +1 -63
  53. data/steep.gemspec +1 -1
  54. metadata +13 -10
  55. data/lib/steep/drivers/trace_printer.rb +0 -29
  56. data/lib/steep/interface/method.rb +0 -78
  57. 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.instance_variables.each do |name, var|
119
- if parent = var.parent_variable
120
- var_type = checker.factory.type(var.type)
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
- relation = Subtyping::Relation.new(sub_type: var_type, super_type: parent_type)
124
- result1 = checker.check(
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
- result2 = checker.check(
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: var.type.location,
143
- var_type: var_type,
144
- parent_type: parent_type
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
- ancestors = builder.ancestor_builder.one_instance_ancestors(name)
151
- mixin_constraints(definition, ancestors.included_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
152
- checker.check(
153
- relation,
154
- self_type: AST::Types::Self.new,
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
- definition.each_type do |type|
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
- definition.each_type do |type|
225
- validate_type type
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).each_type do |type|
237
- validate_type type
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
- builder.expand_alias(name).tap do |type|
284
- validate_type(type)
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::ErrorBase => exn
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