steep 1.7.0 → 1.8.0.dev.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee680022ab2333d1fcfeff84ee0513c389ccfb6cf52fbc04f3f53edace112931
4
- data.tar.gz: 400fd763d24b8154fea38900c988cf651c6a0e646485a1aa4d4e6c5ba285a453
3
+ metadata.gz: 635cc7b37608055562fc399845485f40c065e7300072a2ca194ea15137a0ac11
4
+ data.tar.gz: c16be740c2d1a8a11ece00fc3abbca6b33a715ddbbfb0a210bc8e09287e2c7d5
5
5
  SHA512:
6
- metadata.gz: 6836114d1f2e78eea1b2d19528a480ca234cc02f1339d8c70543e20a6c7b969d59b11a9434290e0fa2a4116ffe8f2b646bb0a9c642a0978102e5752be06ae808
7
- data.tar.gz: 0476bc765f54bba0442aafdd08a64c2985a0d16fe25efaac69f9c3ddad8cca44628d78d1fb62e2c5e0727627cdcddd1a7cdc5987e3de6ef4cdc1e1a5761bcb99
6
+ metadata.gz: 164e5369654bc6ef2bd0ef355b796f3b9ee2c43a1887501cfc0282c8cccedc84a2d3a61a4ca257c51ea2500f342f5ad7c9496e03b29d1433aee81c020bae18db
7
+ data.tar.gz: 03ba49762f19dda444ff5a73a08eca0417ef02d89bed4039ccbc01c07cb1d59e05714583cfaa654dff5597e55ebc55844a038483ec1a46068cd8613f9d575c78
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.7.1 (2024-06-12)
4
+
5
+ ### Type checker core
6
+
7
+ * Fix subtyping issues ([#1165](https://github.com/soutaro/steep/pull/1165))
8
+
3
9
  ## 1.7.0 (2024-06-07)
4
10
 
5
11
  ### Type checker core
data/doc/shape.md CHANGED
@@ -24,7 +24,9 @@ Shape (_Foo) {
24
24
  Note that the `self` type in the example is resolved to `_Foo` during shape calculation.
25
25
 
26
26
  The shape calculation of an object is straightforward. Calculate a `RBS::Definition` of a class singleton/instance, or an interface, and translate the data structure to a `Shape` object. But there are a few things to consider.
27
+
27
28
  ## Tuple, record, and proc types
29
+
28
30
  The shape of tuple, record, or proc types are based on their base types -- Array, Hash, or Proc classes --, but with specialized method types.
29
31
 
30
32
  ```
@@ -37,16 +39,22 @@ Shape ([Integer, String]) {
37
39
  ```
38
40
 
39
41
  The specialization is implemented as a part of shape calculation.
42
+
40
43
  ## Special methods
44
+
41
45
  Steep recognizes some special methods for type narrowing, including `#is_a?`, `#===`, `#nil?`, ... These methods are defined with normal RBS syntax, but the method types in shapes are transformed to types using logic types.
42
46
 
43
47
  The shape calculation inserts the specialized methods with these special methods.
48
+
44
49
  ## `self` types
50
+
45
51
  There are two cases of `self` types to consider during shape calculation.
46
52
 
47
53
  1. `self` types included in the shape of a type
48
54
  2. `self` types included in given types
55
+
49
56
  ### 1. `self` types included in the shape of a type
57
+
50
58
  `self` types may be included in a class or interface definition.
51
59
 
52
60
  ```rbs
@@ -62,7 +70,9 @@ Shape (_Foo) {
62
70
  itself: () -> _Foo
63
71
  }
64
72
  ```
73
+
65
74
  ### 2. `self` types included in given types
75
+
66
76
  Unlike `self` types included in definitions, `self` types in given types should be preserved.
67
77
 
68
78
  ```rbs
@@ -100,7 +110,9 @@ end
100
110
  ```
101
111
 
102
112
  We want the type of `foo.get` to be `self`, not `Foo`, to avoid a type error being detected.
113
+
103
114
  ## Shape of `self` types
115
+
104
116
  We also want `self` type if `self` is the type of the shape.
105
117
 
106
118
  ```rb
@@ -154,7 +166,9 @@ Shape (Foo | Bar) {
154
166
  So, the resulting type of `self.foo` where the type of `self` is `Foo | Bar`, would be `Integer | Foo | Bar`. But, actually, it won't be `Foo` because the `self` comes from `Bar`.
155
167
 
156
168
  This is an incorrect result, but Steep is doing this right now.
169
+
157
170
  ## `class` and `instance` types
171
+
158
172
  The shape calculation provides limited support for `class` and `instance` types.
159
173
 
160
174
  1. `class`/`instance` types from the definition are resolved
@@ -162,13 +176,17 @@ The shape calculation provides limited support for `class` and `instance` types.
162
176
  3. Shape of `class`/`instance` types are resolved to configuration's `class_type` and `instance_type`, and the translated types are used to calculate the shape
163
177
 
164
178
  It's different from `self` types except case #2. The relationship between `self`/`class`/`instance` is not trivial in Ruby. All of them might be resolved to any type, which means calculating one from another of them is simply impossible.
179
+
165
180
  ## Public methods, private methods
181
+
166
182
  `Shape` objects have a flag of if the shape is for *public* method calls or *private* method calls. Private method call is a form of `foo()` or `self.foo()` -- when the receiver is omitted or `self`. Public method calls are anything else.
167
183
 
168
184
  The shape calculation starts with *private methods*, and the `Shape#public_shape` method returns another shape that only has *public* methods.
169
185
 
170
186
  > Note that the private shape calculation is required even on public method calls. This means a possible chance of future optimizations.
187
+
171
188
  ## Lazy method type calculation
189
+
172
190
  We rarely need all of the methods available for an object. If we want to type check a method call, we only need the method type of that method. All other methods can be just ignored.
173
191
 
174
192
  *Lazy method type calculation* is introduced for that case. Instead of calculating the types of all of the methods, it registers a block that computes the method type.
@@ -9,8 +9,6 @@ module Steep
9
9
  @class_type = class_type
10
10
  @instance_type = instance_type
11
11
  @variable_bounds = variable_bounds
12
-
13
- validate
14
12
  end
15
13
 
16
14
  def self.empty
@@ -23,11 +21,16 @@ module Steep
23
21
  end
24
22
  end
25
23
 
26
- def validate
24
+ def validate_self_type
27
25
  validate_fvs(:self_type, self_type)
26
+ end
27
+
28
+ def validate_instance_type
28
29
  validate_fvs(:instance_type, instance_type)
30
+ end
31
+
32
+ def validate_class_type
29
33
  validate_fvs(:class_type, class_type)
30
- self
31
34
  end
32
35
 
33
36
  def validate_fvs(name, type)
@@ -37,6 +40,7 @@ module Steep
37
40
  raise "#{name} cannot include 'self' type: #{type}"
38
41
  end
39
42
  if fvs.include?(AST::Types::Instance.instance)
43
+ Steep.logger.fatal { "#{name} cannot include 'instance' type: #{type}" }
40
44
  raise "#{name} cannot include 'instance' type: #{type}"
41
45
  end
42
46
  if fvs.include?(AST::Types::Class.instance)
@@ -87,12 +91,15 @@ module Steep
87
91
  def raw_shape(type, config)
88
92
  case type
89
93
  when AST::Types::Self
94
+ config.validate_self_type
90
95
  self_type = config.self_type or raise
91
96
  self_shape(self_type, config)
92
97
  when AST::Types::Instance
98
+ config.validate_instance_type
93
99
  instance_type = config.instance_type or raise
94
100
  raw_shape(instance_type, config)
95
101
  when AST::Types::Class
102
+ config.validate_class_type
96
103
  klass_type = config.class_type or raise
97
104
  raw_shape(klass_type, config)
98
105
  when AST::Types::Name::Singleton
@@ -5,10 +5,23 @@ module Steep
5
5
  Declarations = RBS::AST::Declarations
6
6
 
7
7
  attr_reader :checker
8
+ attr_reader :context
8
9
 
9
10
  def initialize(checker:)
10
11
  @checker = checker
11
12
  @errors = []
13
+ @context = []
14
+ end
15
+
16
+ def push_context(self_type: latest_context[0], class_type: latest_context[1], instance_type: latest_context[2])
17
+ @context.push([self_type, class_type, instance_type])
18
+ yield
19
+ ensure
20
+ @context.pop
21
+ end
22
+
23
+ def latest_context
24
+ context.last || [nil, nil, nil]
12
25
  end
13
26
 
14
27
  def has_error?
@@ -72,11 +85,13 @@ module Steep
72
85
 
73
86
  constraints = Subtyping::Constraints.empty
74
87
 
88
+ self_type, class_type, instance_type = latest_context
89
+
75
90
  checker.check(
76
91
  Subtyping::Relation.new(sub_type: arg_type, super_type: upper_bound_type),
77
- self_type: AST::Types::Self.instance,
78
- class_type: nil,
79
- instance_type: nil,
92
+ self_type: self_type,
93
+ class_type: class_type,
94
+ instance_type: instance_type,
80
95
  constraints: constraints
81
96
  ).else do |result|
82
97
  @errors << Diagnostic::Signature::UnsatisfiableTypeApplication.new(
@@ -236,25 +251,113 @@ module Steep
236
251
  end
237
252
  end
238
253
 
239
- def validate_one_class_decl(name)
254
+ def validate_one_class_decl(name, entry)
240
255
  rescue_validation_errors(name) do
241
256
  Steep.logger.debug { "Validating class definition `#{name}`..." }
242
257
 
258
+ class_type = AST::Types::Name::Singleton.new(name: name, location: nil)
259
+ instance_type = AST::Types::Name::Instance.new(
260
+ name: name,
261
+ args: entry.type_params.map { AST::Types::Any.new(location: nil) },
262
+ location: nil
263
+ )
264
+
243
265
  Steep.logger.tagged "#{name}" do
244
266
  builder.build_instance(name).tap do |definition|
245
267
  upper_bounds = definition.type_params_decl.each.with_object({}) do |param, bounds|
246
268
  bounds[param.name] = factory.type_opt(param.upper_bound)
247
269
  end
248
270
 
249
- checker.push_variable_bounds(upper_bounds) do
271
+ self_type = AST::Types::Name::Instance.new(
272
+ name: name,
273
+ args: entry.type_params.map { AST::Types::Var.new(name: _1.name) },
274
+ location: nil
275
+ )
276
+
277
+ push_context(self_type: self_type, class_type: class_type, instance_type: instance_type) do
278
+ checker.push_variable_bounds(upper_bounds) do
279
+ definition.instance_variables.each do |name, var|
280
+ if parent = var.parent_variable
281
+ var_type = checker.factory.type(var.type)
282
+ parent_type = checker.factory.type(parent.type)
283
+
284
+ relation = Subtyping::Relation.new(sub_type: var_type, super_type: parent_type)
285
+ result1 = checker.check(relation, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
286
+ result2 = checker.check(relation.flip, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
287
+
288
+ unless result1.success? and result2.success?
289
+ @errors << Diagnostic::Signature::InstanceVariableTypeError.new(
290
+ name: name,
291
+ location: var.type.location,
292
+ var_type: var_type,
293
+ parent_type: parent_type
294
+ )
295
+ end
296
+ end
297
+ end
298
+
299
+ ancestors = builder.ancestor_builder.one_instance_ancestors(name)
300
+ mixin_constraints(definition, ancestors.included_modules || raise, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
301
+ checker.check(
302
+ relation,
303
+ self_type: AST::Types::Self.instance,
304
+ instance_type: AST::Types::Instance.instance,
305
+ class_type: AST::Types::Class.instance,
306
+ constraints: Subtyping::Constraints.empty
307
+ ).else do
308
+ raise if ancestor.source.is_a?(Symbol)
309
+
310
+ @errors << Diagnostic::Signature::ModuleSelfTypeError.new(
311
+ name: name,
312
+ location: ancestor.source&.location || raise,
313
+ ancestor: ancestor,
314
+ relation: relation
315
+ )
316
+ end
317
+ end
318
+
319
+ ancestors.each_ancestor do |ancestor|
320
+ case ancestor
321
+ when RBS::Definition::Ancestor::Instance
322
+ validate_ancestor_application(name, ancestor)
323
+ end
324
+ end
325
+
326
+ validate_definition_type(definition)
327
+ end
328
+ end
329
+ end
330
+
331
+ builder.build_singleton(name).tap do |definition|
332
+ entry =
333
+ case definition.entry
334
+ when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
335
+ definition.entry
336
+ else
337
+ raise
338
+ end
339
+
340
+ push_context(self_type: class_type, class_type: class_type, instance_type: instance_type) do
250
341
  definition.instance_variables.each do |name, var|
251
342
  if parent = var.parent_variable
252
343
  var_type = checker.factory.type(var.type)
253
344
  parent_type = checker.factory.type(parent.type)
254
345
 
255
346
  relation = Subtyping::Relation.new(sub_type: var_type, super_type: parent_type)
256
- result1 = checker.check(relation, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
257
- result2 = checker.check(relation.flip, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
347
+ result1 = checker.check(
348
+ relation,
349
+ self_type: AST::Types::Self.instance,
350
+ instance_type: AST::Types::Instance.instance,
351
+ class_type: AST::Types::Class.instance,
352
+ constraints: Subtyping::Constraints.empty
353
+ )
354
+ result2 = checker.check(
355
+ relation.flip,
356
+ self_type: AST::Types::Self.instance,
357
+ instance_type: AST::Types::Instance.instance,
358
+ class_type: AST::Types::Class.instance,
359
+ constraints: Subtyping::Constraints.empty
360
+ )
258
361
 
259
362
  unless result1.success? and result2.success?
260
363
  @errors << Diagnostic::Signature::InstanceVariableTypeError.new(
@@ -267,11 +370,32 @@ module Steep
267
370
  end
268
371
  end
269
372
 
270
- ancestors = builder.ancestor_builder.one_instance_ancestors(name)
271
- mixin_constraints(definition, ancestors.included_modules || raise, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
373
+ definition.class_variables.each do |name, var|
374
+ if var.declared_in == definition.type_name
375
+ if (parent = var.parent_variable) && var.declared_in != parent.declared_in
376
+ class_var = entry.decls.flat_map {|decl| decl.decl.members }.find do |member|
377
+ member.is_a?(RBS::AST::Members::ClassVariable) && member.name == name
378
+ end
379
+
380
+ if class_var
381
+ loc = class_var.location #: RBS::Location[untyped, untyped]?
382
+ @errors << Diagnostic::Signature::ClassVariableDuplicationError.new(
383
+ class_name: definition.type_name,
384
+ other_class_name: parent.declared_in,
385
+ variable_name: name,
386
+ location: loc&.[](:name) || raise
387
+ )
388
+ end
389
+ end
390
+ end
391
+ end
392
+
393
+ ancestors = builder.ancestor_builder.one_singleton_ancestors(name)
394
+ ancestors.extended_modules or raise
395
+ mixin_constraints(definition, ancestors.extended_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
272
396
  checker.check(
273
397
  relation,
274
- self_type: AST::Types::Self.instance,
398
+ self_type: AST::Types::Self.instance ,
275
399
  instance_type: AST::Types::Instance.instance,
276
400
  class_type: AST::Types::Class.instance,
277
401
  constraints: Subtyping::Constraints.empty
@@ -286,7 +410,6 @@ module Steep
286
410
  )
287
411
  end
288
412
  end
289
-
290
413
  ancestors.each_ancestor do |ancestor|
291
414
  case ancestor
292
415
  when RBS::Definition::Ancestor::Instance
@@ -297,97 +420,6 @@ module Steep
297
420
  validate_definition_type(definition)
298
421
  end
299
422
  end
300
-
301
- builder.build_singleton(name).tap do |definition|
302
- entry =
303
- case definition.entry
304
- when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
305
- definition.entry
306
- else
307
- raise
308
- end
309
-
310
- definition.instance_variables.each do |name, var|
311
- if parent = var.parent_variable
312
- var_type = checker.factory.type(var.type)
313
- parent_type = checker.factory.type(parent.type)
314
-
315
- relation = Subtyping::Relation.new(sub_type: var_type, super_type: parent_type)
316
- result1 = checker.check(
317
- relation,
318
- self_type: AST::Types::Self.instance,
319
- instance_type: AST::Types::Instance.instance,
320
- class_type: AST::Types::Class.instance,
321
- constraints: Subtyping::Constraints.empty
322
- )
323
- result2 = checker.check(
324
- relation.flip,
325
- self_type: AST::Types::Self.instance,
326
- instance_type: AST::Types::Instance.instance,
327
- class_type: AST::Types::Class.instance,
328
- constraints: Subtyping::Constraints.empty
329
- )
330
-
331
- unless result1.success? and result2.success?
332
- @errors << Diagnostic::Signature::InstanceVariableTypeError.new(
333
- name: name,
334
- location: var.type.location,
335
- var_type: var_type,
336
- parent_type: parent_type
337
- )
338
- end
339
- end
340
- end
341
-
342
- definition.class_variables.each do |name, var|
343
- if var.declared_in == definition.type_name
344
- if (parent = var.parent_variable) && var.declared_in != parent.declared_in
345
- class_var = entry.decls.flat_map {|decl| decl.decl.members }.find do |member|
346
- member.is_a?(RBS::AST::Members::ClassVariable) && member.name == name
347
- end
348
-
349
- if class_var
350
- loc = class_var.location #: RBS::Location[untyped, untyped]?
351
- @errors << Diagnostic::Signature::ClassVariableDuplicationError.new(
352
- class_name: definition.type_name,
353
- other_class_name: parent.declared_in,
354
- variable_name: name,
355
- location: loc&.[](:name) || raise
356
- )
357
- end
358
- end
359
- end
360
- end
361
-
362
- ancestors = builder.ancestor_builder.one_singleton_ancestors(name)
363
- ancestors.extended_modules or raise
364
- mixin_constraints(definition, ancestors.extended_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
365
- checker.check(
366
- relation,
367
- self_type: AST::Types::Self.instance ,
368
- instance_type: AST::Types::Instance.instance,
369
- class_type: AST::Types::Class.instance,
370
- constraints: Subtyping::Constraints.empty
371
- ).else do
372
- raise if ancestor.source.is_a?(Symbol)
373
-
374
- @errors << Diagnostic::Signature::ModuleSelfTypeError.new(
375
- name: name,
376
- location: ancestor.source&.location || raise,
377
- ancestor: ancestor,
378
- relation: relation
379
- )
380
- end
381
- end
382
- ancestors.each_ancestor do |ancestor|
383
- case ancestor
384
- when RBS::Definition::Ancestor::Instance
385
- validate_ancestor_application(name, ancestor)
386
- end
387
- end
388
-
389
- validate_definition_type(definition)
390
- end
391
423
  end
392
424
  end
393
425
  end
@@ -397,7 +429,7 @@ module Steep
397
429
 
398
430
  case entry
399
431
  when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
400
- validate_one_class_decl(name)
432
+ validate_one_class_decl(name, entry)
401
433
  when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
402
434
  validate_one_class_alias(name, entry)
403
435
  end
@@ -453,23 +485,31 @@ module Steep
453
485
  bounds[param.name] = factory.type_opt(param.upper_bound)
454
486
  end
455
487
 
456
- checker.push_variable_bounds(upper_bounds) do
457
- validate_definition_type(definition)
458
-
459
- ancestors = builder.ancestor_builder.one_interface_ancestors(name)
460
- ancestors.each_ancestor do |ancestor|
461
- case ancestor
462
- when RBS::Definition::Ancestor::Instance
463
- # Interface ancestor cannot be other than Interface
464
- ancestor.source.is_a?(Symbol) and raise
465
-
466
- defn = builder.build_interface(ancestor.name)
467
- validate_type_application_constraints(
468
- ancestor.name,
469
- defn.type_params_decl,
470
- ancestor.args,
471
- location: ancestor.source&.location || raise
472
- )
488
+ self_type = AST::Types::Name::Interface.new(
489
+ name: name,
490
+ args: definition.type_params.map { AST::Types::Var.new(name: _1) },
491
+ location: nil
492
+ )
493
+
494
+ push_context(self_type: self_type, class_type: nil, instance_type: nil) do
495
+ checker.push_variable_bounds(upper_bounds) do
496
+ validate_definition_type(definition)
497
+
498
+ ancestors = builder.ancestor_builder.one_interface_ancestors(name)
499
+ ancestors.each_ancestor do |ancestor|
500
+ case ancestor
501
+ when RBS::Definition::Ancestor::Instance
502
+ # Interface ancestor cannot be other than Interface
503
+ ancestor.source.is_a?(Symbol) and raise
504
+
505
+ defn = builder.build_interface(ancestor.name)
506
+ validate_type_application_constraints(
507
+ ancestor.name,
508
+ defn.type_params_decl,
509
+ ancestor.args,
510
+ location: ancestor.source&.location || raise
511
+ )
512
+ end
473
513
  end
474
514
  end
475
515
  end
@@ -519,21 +559,33 @@ module Steep
519
559
  end
520
560
 
521
561
  def validate_one_alias(name, entry = env.type_alias_decls[name])
522
- rescue_validation_errors(name) do
523
- Steep.logger.debug "Validating alias `#{name}`..."
562
+ *, inner_most_outer_module = entry.outer
563
+ if inner_most_outer_module
564
+ class_type = AST::Types::Name::Singleton.new(name: inner_most_outer_module.name, location: nil)
565
+ instance_type = AST::Types::Name::Instance.new(
566
+ name: inner_most_outer_module.name,
567
+ args: inner_most_outer_module.type_params.map { AST::Types::Any.new(location: nil) },
568
+ location: nil
569
+ )
570
+ end
524
571
 
525
- unless name.namespace.empty?
526
- outer = name.namespace.to_type_name
527
- builder.validate_type_name(outer, entry.decl.location&.aref(:name))
528
- end
572
+ push_context(class_type: class_type, instance_type: instance_type, self_type: nil) do
573
+ rescue_validation_errors(name) do
574
+ Steep.logger.debug "Validating alias `#{name}`..."
529
575
 
530
- upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
531
- bounds[param.name] = factory.type_opt(param.upper_bound)
532
- end
576
+ unless name.namespace.empty?
577
+ outer = name.namespace.to_type_name
578
+ builder.validate_type_name(outer, entry.decl.location&.aref(:name))
579
+ end
580
+
581
+ upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
582
+ bounds[param.name] = factory.type_opt(param.upper_bound)
583
+ end
533
584
 
534
- validator.validate_type_alias(entry: entry) do |type|
535
- checker.push_variable_bounds(upper_bounds) do
536
- validate_type(entry.decl.type)
585
+ validator.validate_type_alias(entry: entry) do |type|
586
+ checker.push_variable_bounds(upper_bounds) do
587
+ validate_type(entry.decl.type)
588
+ end
537
589
  end
538
590
  end
539
591
  end
data/lib/steep/source.rb CHANGED
@@ -459,12 +459,14 @@ module Steep
459
459
  case node.type
460
460
  when :lvasgn, :ivasgn, :gvasgn, :cvasgn, :casgn
461
461
  # Skip
462
+ when :return, :break, :next
463
+ # Skip
464
+ when :def, :defs
465
+ # Skip
462
466
  when :masgn
463
467
  lhs, rhs = node.children
464
468
  node = node.updated(nil, [lhs, insert_type_node(rhs, comments)])
465
469
  return adjust_location(node)
466
- when :return, :break, :next
467
- # Skip
468
470
  when :begin
469
471
  location = node.loc #: Parser::Source::Map & Parser::AST::_Collection
470
472
  if location.begin
@@ -475,6 +477,15 @@ module Steep
475
477
  return assertion_node(node, last_comment)
476
478
  end
477
479
  else
480
+ if (receiver, name, * = deconstruct_send_node(node))
481
+ if receiver.nil?
482
+ if name == :attr_reader || name == :attr_writer || name == :attr_accessor
483
+ child_assertions = comments.except(last_line)
484
+ node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
485
+ return adjust_location(node)
486
+ end
487
+ end
488
+ end
478
489
  child_assertions = comments.except(last_line)
479
490
  node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
480
491
  node = adjust_location(node)
@@ -540,6 +551,21 @@ module Steep
540
551
  ]
541
552
  )
542
553
  )
554
+ when :def
555
+ name, args, body = node.children
556
+ assertion_location = args&.location&.expression || (_ = node.location).name
557
+ no_assertion_comments = comments.except(assertion_location.last_line)
558
+ args = insert_type_node(args, no_assertion_comments)
559
+ body = insert_type_node(body, comments) if body
560
+ return adjust_location(node.updated(nil, [name, args, body]))
561
+ when :defs
562
+ object, name, args, body = node.children
563
+ assertion_location = args&.location&.expression || (_ = node.location).name
564
+ no_assertion_comments = comments.except(assertion_location.last_line)
565
+ object = insert_type_node(object, no_assertion_comments)
566
+ args = insert_type_node(args, no_assertion_comments)
567
+ body = insert_type_node(body, comments) if body
568
+ return adjust_location(node.updated(nil, [object, name, args, body]))
543
569
  else
544
570
  adjust_location(
545
571
  map_child_node(node, nil) {|child| insert_type_node(child, comments) }
@@ -798,33 +798,37 @@ module Steep
798
798
  end
799
799
 
800
800
  def check_method_type(name, relation)
801
- relation.method!
801
+ Steep.logger.tagged "#{name} : #{relation.sub_type} <: #{relation.super_type}" do
802
+ relation.method!
802
803
 
803
- sub_type, super_type = relation
804
+ sub_type, super_type = relation
804
805
 
805
- sub_type.type_params.empty? or raise "Expected monomorphic method type: #{sub_type}"
806
- super_type.type_params.empty? or raise "Expected monomorphic method type: #{super_type}"
806
+ sub_type.type_params.empty? or raise "Expected monomorphic method type: #{sub_type}"
807
+ super_type.type_params.empty? or raise "Expected monomorphic method type: #{super_type}"
807
808
 
808
- All(relation) do |result|
809
- type_relation = Relation.new(sub_type: sub_type.type, super_type: super_type.type)
810
-
811
- ret = expand_block_given(name, Relation.new(sub_type: sub_type.block, super_type: super_type.block))
812
-
813
- case ret
814
- when true
815
- result.add(type_relation) { check_function(name, type_relation) }
816
- when Relation
817
- result.add(type_relation) { check_function(name, type_relation) }
818
- result.add(ret) do
819
- All(ret) do |result|
820
- result.add_result(check_self_type_binding(ret, ret.super_type.self_type, ret.sub_type.self_type))
821
- result.add(Relation(ret.super_type.type, ret.sub_type.type)) do |block_relation|
822
- check_function(name, block_relation)
809
+ All(relation) do |result|
810
+ type_relation = Relation.new(sub_type: sub_type.type, super_type: super_type.type)
811
+
812
+ ret = expand_block_given(name, Relation.new(sub_type: sub_type.block, super_type: super_type.block))
813
+
814
+ case ret
815
+ when true
816
+ result.add(type_relation) { check_function(name, type_relation) }
817
+ when Relation
818
+ result.add(type_relation) { check_function(name, type_relation) }
819
+ result.add(ret) do
820
+ All(ret) do |result|
821
+ result.add_result(check_self_type_binding(ret, ret.super_type.self_type, ret.sub_type.self_type))
822
+ result.add(Relation(ret.super_type.type, ret.sub_type.type)) do |block_relation|
823
+ check_function(name, block_relation)
824
+ end
823
825
  end
824
826
  end
827
+ when Result::Failure
828
+ result.add(ret.relation) { ret }
829
+ end.tap do |ret|
830
+ Steep.logger.debug "result=#{ret.class}"
825
831
  end
826
- when Result::Failure
827
- result.add(ret.relation) { ret }
828
832
  end
829
833
  end
830
834
  end
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.7.0"
2
+ VERSION = "1.8.0.dev.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steep
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.8.0.dev.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-07 00:00:00.000000000 Z
11
+ date: 2024-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser