steep 0.47.1 → 0.49.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/Gemfile.lock +7 -7
  4. data/lib/steep/ast/types/any.rb +2 -0
  5. data/lib/steep/ast/types/boolean.rb +2 -0
  6. data/lib/steep/ast/types/bot.rb +2 -0
  7. data/lib/steep/ast/types/class.rb +2 -0
  8. data/lib/steep/ast/types/factory.rb +162 -138
  9. data/lib/steep/ast/types/helper.rb +8 -0
  10. data/lib/steep/ast/types/instance.rb +2 -0
  11. data/lib/steep/ast/types/intersection.rb +4 -0
  12. data/lib/steep/ast/types/literal.rb +2 -0
  13. data/lib/steep/ast/types/logic.rb +2 -0
  14. data/lib/steep/ast/types/name.rb +6 -0
  15. data/lib/steep/ast/types/nil.rb +2 -0
  16. data/lib/steep/ast/types/proc.rb +9 -0
  17. data/lib/steep/ast/types/record.rb +4 -0
  18. data/lib/steep/ast/types/self.rb +2 -0
  19. data/lib/steep/ast/types/top.rb +2 -0
  20. data/lib/steep/ast/types/tuple.rb +4 -0
  21. data/lib/steep/ast/types/union.rb +4 -0
  22. data/lib/steep/ast/types/var.rb +16 -3
  23. data/lib/steep/ast/types/void.rb +2 -0
  24. data/lib/steep/diagnostic/ruby.rb +36 -11
  25. data/lib/steep/diagnostic/signature.rb +56 -0
  26. data/lib/steep/drivers/check.rb +2 -2
  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 +4 -1
  35. data/lib/steep/signature/validator.rb +228 -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 +576 -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 +3 -3
  46. data/sample/lib/length.rb +35 -0
  47. data/sample/sig/length.rbs +34 -0
  48. data/smoke/diagnostics/proc_type_expected.rb +3 -0
  49. data/smoke/diagnostics/test_expectations.yml +12 -0
  50. data/smoke/diagnostics-rbs/nonregular-type-alias.rbs +3 -0
  51. data/smoke/diagnostics-rbs/recursive-type-alias.rbs +3 -0
  52. data/smoke/diagnostics-rbs/test_expectations.yml +57 -12
  53. data/smoke/tsort/a.rb +1 -1
  54. data/smoke/tsort/test_expectations.yml +1 -63
  55. data/steep.gemspec +1 -1
  56. metadata +14 -10
  57. data/lib/steep/drivers/trace_printer.rb +0 -29
  58. data/lib/steep/interface/method.rb +0 -78
  59. 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.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)
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
- relation = Subtyping::Relation.new(sub_type: var_type, super_type: parent_type)
124
- result1 = checker.check(
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
- 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(
268
+ ).else do
269
+ @errors << Diagnostic::Signature::ModuleSelfTypeError.new(
141
270
  name: name,
142
- location: var.type.location,
143
- var_type: var_type,
144
- parent_type: parent_type
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
- 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
- )
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
- definition.each_type do |type|
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
- definition.each_type do |type|
225
- validate_type type
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).each_type do |type|
237
- validate_type type
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
- builder.expand_alias(name).tap do |type|
284
- validate_type(type)
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::ErrorBase => exn
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