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.
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