steep 0.22.0 → 0.28.0

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -1
  3. data/bin/smoke_runner.rb +3 -4
  4. data/lib/steep.rb +1 -1
  5. data/lib/steep/ast/builtin.rb +2 -20
  6. data/lib/steep/ast/types.rb +5 -3
  7. data/lib/steep/ast/types/any.rb +1 -3
  8. data/lib/steep/ast/types/boolean.rb +1 -3
  9. data/lib/steep/ast/types/bot.rb +1 -3
  10. data/lib/steep/ast/types/class.rb +2 -2
  11. data/lib/steep/ast/types/factory.rb +106 -55
  12. data/lib/steep/ast/types/helper.rb +6 -0
  13. data/lib/steep/ast/types/instance.rb +2 -2
  14. data/lib/steep/ast/types/intersection.rb +20 -13
  15. data/lib/steep/ast/types/literal.rb +1 -3
  16. data/lib/steep/ast/types/name.rb +15 -67
  17. data/lib/steep/ast/types/nil.rb +1 -3
  18. data/lib/steep/ast/types/proc.rb +5 -2
  19. data/lib/steep/ast/types/record.rb +9 -4
  20. data/lib/steep/ast/types/self.rb +1 -1
  21. data/lib/steep/ast/types/top.rb +1 -3
  22. data/lib/steep/ast/types/tuple.rb +5 -3
  23. data/lib/steep/ast/types/union.rb +16 -9
  24. data/lib/steep/ast/types/var.rb +2 -2
  25. data/lib/steep/ast/types/void.rb +1 -3
  26. data/lib/steep/drivers/check.rb +4 -0
  27. data/lib/steep/errors.rb +14 -0
  28. data/lib/steep/interface/interface.rb +5 -62
  29. data/lib/steep/interface/method_type.rb +383 -92
  30. data/lib/steep/interface/substitution.rb +48 -6
  31. data/lib/steep/project/completion_provider.rb +1 -1
  32. data/lib/steep/project/hover_content.rb +1 -1
  33. data/lib/steep/project/target.rb +5 -2
  34. data/lib/steep/server/base_worker.rb +5 -3
  35. data/lib/steep/server/code_worker.rb +2 -0
  36. data/lib/steep/server/master.rb +10 -1
  37. data/lib/steep/source.rb +4 -3
  38. data/lib/steep/subtyping/check.rb +49 -60
  39. data/lib/steep/type_construction.rb +629 -366
  40. data/lib/steep/type_inference/block_params.rb +5 -0
  41. data/lib/steep/type_inference/constant_env.rb +1 -1
  42. data/lib/steep/type_inference/context.rb +8 -0
  43. data/lib/steep/type_inference/context_array.rb +4 -3
  44. data/lib/steep/type_inference/logic.rb +31 -0
  45. data/lib/steep/typing.rb +7 -0
  46. data/lib/steep/version.rb +1 -1
  47. data/smoke/alias/a.rb +1 -1
  48. data/smoke/case/a.rb +1 -1
  49. data/smoke/hash/d.rb +1 -1
  50. data/smoke/if/a.rb +1 -1
  51. data/smoke/module/a.rb +1 -1
  52. data/smoke/rescue/a.rb +4 -13
  53. data/steep.gemspec +1 -1
  54. metadata +5 -5
@@ -26,7 +26,32 @@ module Steep
26
26
  end
27
27
 
28
28
  def self.empty
29
- new(dictionary: {}, instance_type: AST::Types::Instance.new, module_type: AST::Types::Class.new, self_type: AST::Types::Self.new)
29
+ new(dictionary: {},
30
+ instance_type: INSTANCE_TYPE,
31
+ module_type: CLASS_TYPE,
32
+ self_type: SELF_TYPE)
33
+ end
34
+
35
+ def empty?
36
+ dictionary.empty? &&
37
+ instance_type.is_a?(AST::Types::Instance) &&
38
+ module_type.is_a?(AST::Types::Class) &&
39
+ self_type.is_a?(AST::Types::Self)
40
+ end
41
+
42
+ INSTANCE_TYPE = AST::Types::Instance.new
43
+ CLASS_TYPE = AST::Types::Class.new
44
+ SELF_TYPE = AST::Types::Self.new
45
+
46
+ def domain
47
+ set = Set.new
48
+
49
+ set.merge(dictionary.keys)
50
+ set << INSTANCE_TYPE unless instance_type.is_a?(AST::Types::Instance)
51
+ set << CLASS_TYPE unless instance_type.is_a?(AST::Types::Class)
52
+ set << SELF_TYPE unless instance_type.is_a?(AST::Types::Self)
53
+
54
+ set
30
55
  end
31
56
 
32
57
  def to_s
@@ -65,22 +90,39 @@ module Steep
65
90
 
66
91
  def except(vars)
67
92
  self.class.new(
68
- dictionary: dictionary.reject {|k, _| vars.include?(k) },
93
+ dictionary: dictionary,
69
94
  instance_type: instance_type,
70
95
  module_type: module_type,
71
96
  self_type: self_type
72
- )
97
+ ).except!(vars)
73
98
  end
74
99
 
75
- def merge!(s)
100
+ def except!(vars)
101
+ vars.each do |var|
102
+ dictionary.delete(var)
103
+ end
104
+
105
+ self
106
+ end
107
+
108
+ def merge!(s, overwrite: false)
76
109
  dictionary.transform_values! {|ty| ty.subst(s) }
77
110
  dictionary.merge!(s.dictionary) do |key, a, b|
78
111
  if a == b
79
112
  a
80
113
  else
81
- raise "Duplicated key on merge!: #{key}, #{a}, #{b}"
114
+ if overwrite
115
+ b
116
+ else
117
+ raise "Duplicated key on merge!: #{key}, #{a}, #{b} (#{self})"
118
+ end
82
119
  end
83
120
  end
121
+
122
+ @instance_type = instance_type.subst(s)
123
+ @module_type = module_type.subst(s)
124
+ @self_type = self_type.subst(s)
125
+
84
126
  self
85
127
  end
86
128
 
@@ -92,7 +134,7 @@ module Steep
92
134
  end
93
135
 
94
136
  def add!(v, ty)
95
- merge!(Substitution.new(dictionary: { v => ty }, instance_type: nil, module_type: nil, self_type: nil))
137
+ merge!(Substitution.new(dictionary: { v => ty }, instance_type: instance_type, module_type: module_type, self_type: self_type))
96
138
  end
97
139
  end
98
140
  end
@@ -234,7 +234,7 @@ module Steep
234
234
  when AST::Types::Name::Instance
235
235
  type_name = subtyping.factory.type_name_1(type.name)
236
236
  subtyping.factory.definition_builder.build_instance(type_name)
237
- when AST::Types::Name::Class, AST::Types::Name::Module
237
+ when AST::Types::Name::Singleton
238
238
  type_name = subtyping.factory.type_name_1(type.name)
239
239
  subtyping.factory.definition_builder.build_singleton(type_name)
240
240
  when AST::Types::Name::Interface
@@ -92,7 +92,7 @@ module Steep
92
92
  method_definition
93
93
  ]
94
94
  end
95
- when AST::Types::Name::Class
95
+ when AST::Types::Name::Singleton
96
96
  method_definition = method_definition_for(factory, receiver_type.name, singleton_method: method_name)
97
97
  if method_definition&.defined_in
98
98
  owner_name = factory.type_name(method_definition.defined_in)
@@ -172,6 +172,7 @@ module Steep
172
172
  timestamp: Time.now
173
173
  )
174
174
  rescue => exn
175
+ Steep.log_error exn
175
176
  @status = SignatureOtherErrorStatus.new(error: exn, timestamp: Time.now)
176
177
  end
177
178
  end
@@ -194,8 +195,10 @@ module Steep
194
195
  type_check_sources = []
195
196
 
196
197
  target_sources.each do |file|
197
- if file.type_check(check, timestamp)
198
- type_check_sources << file
198
+ Steep.logger.tagged("path=#{file.path}") do
199
+ if file.type_check(check, timestamp)
200
+ type_check_sources << file
201
+ end
199
202
  end
200
203
  end
201
204
 
@@ -12,6 +12,7 @@ module Steep
12
12
  @project = project
13
13
  @reader = reader
14
14
  @writer = writer
15
+ @shutdown = false
15
16
  end
16
17
 
17
18
  def handle_request(request)
@@ -28,7 +29,7 @@ module Steep
28
29
  Steep.logger.formatter.push_tags(*tags)
29
30
  Steep.logger.tagged "background" do
30
31
  while job = queue.pop
31
- handle_job(job)
32
+ handle_job(job) unless @shutdown
32
33
  end
33
34
  end
34
35
  end
@@ -38,11 +39,12 @@ module Steep
38
39
  reader.read do |request|
39
40
  case request[:method]
40
41
  when "shutdown"
41
- # nop
42
+ @shutdown = true
43
+ writer.write(id: request[:id], result: nil)
42
44
  when "exit"
43
45
  break
44
46
  else
45
- handle_request(request)
47
+ handle_request(request) unless @shutdown
46
48
  end
47
49
  end
48
50
  ensure
@@ -139,6 +139,8 @@ module Steep
139
139
  end
140
140
 
141
141
  def handle_job(job)
142
+ sleep 0.1
143
+
142
144
  path, version, target = job
143
145
  if !version || target_files[path] == version
144
146
  typecheck_file(path, target)
@@ -23,6 +23,7 @@ module Steep
23
23
  @signature_worker = signature_worker
24
24
  @code_workers = code_workers
25
25
  @worker_to_paths = {}
26
+ @shutdown_request_id = nil
26
27
  end
27
28
 
28
29
  def start
@@ -59,7 +60,14 @@ module Steep
59
60
  end
60
61
 
61
62
  while job = queue.pop
62
- writer.write(job)
63
+ if @shutdown_request_id
64
+ if job[:id] == @shutdown_request_id
65
+ writer.write(job)
66
+ break
67
+ end
68
+ else
69
+ writer.write(job)
70
+ end
63
71
  end
64
72
 
65
73
  writer.io.close
@@ -154,6 +162,7 @@ module Steep
154
162
 
155
163
  when "shutdown"
156
164
  queue << { id: id, result: nil }
165
+ @shutdown_request_id = id
157
166
 
158
167
  when "exit"
159
168
  queue << nil
@@ -38,7 +38,7 @@ module Steep
38
38
  end
39
39
 
40
40
  def self.parser
41
- ::Parser::Ruby25.new(Builder.new).tap do |parser|
41
+ ::Parser::Ruby27.new(Builder.new).tap do |parser|
42
42
  parser.diagnostics.all_errors_are_fatal = true
43
43
  parser.diagnostics.ignore_warnings = true
44
44
  end
@@ -60,7 +60,7 @@ module Steep
60
60
  _, comments, _ = yield_self do
61
61
  buffer = ::Parser::Source::Buffer.new(path.to_s)
62
62
  buffer.source = source_code
63
- parser = ::Parser::Ruby25.new
63
+ parser = ::Parser::Ruby27.new
64
64
 
65
65
  parser.tokenize(buffer)
66
66
  end
@@ -79,6 +79,7 @@ module Steep
79
79
  end
80
80
 
81
81
  mapping = {}
82
+
82
83
  construct_mapping(node: node, annotations: annotations, mapping: mapping)
83
84
 
84
85
  annotations.each do |annot|
@@ -185,7 +186,7 @@ module Steep
185
186
  construct_mapping(node: node.children[0], annotations: annotations, mapping: mapping, line_range: nil)
186
187
  end
187
188
 
188
- if node.loc.else
189
+ if node.children.last
189
190
  else_node = node.children.last
190
191
  else_start = node.loc.else.last_line
191
192
  else_end = node.loc.end.line
@@ -42,9 +42,8 @@ module Steep
42
42
  )
43
43
  end
44
44
  when RBS::Definition::Ancestor::Singleton
45
- AST::Types::Name::Class.new(
45
+ AST::Types::Name::Singleton.new(
46
46
  name: name,
47
- constructor: nil,
48
47
  location: nil
49
48
  )
50
49
  end
@@ -78,9 +77,8 @@ module Steep
78
77
  )
79
78
  end
80
79
  when RBS::Definition::Ancestor::Singleton
81
- AST::Types::Name::Class.new(
80
+ AST::Types::Name::Singleton.new(
82
81
  name: name,
83
- constructor: nil,
84
82
  location: nil
85
83
  )
86
84
  end
@@ -180,14 +178,13 @@ module Steep
180
178
  constraints: constraints
181
179
  )
182
180
 
183
- when relation.sub_type.is_a?(AST::Types::Literal)
184
- check(
185
- Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type),
186
- self_type: self_type,
187
- assumption: assumption,
188
- trace: trace,
189
- constraints: constraints
190
- )
181
+ when relation.super_type.is_a?(AST::Types::Var) && constraints.unknown?(relation.super_type.name)
182
+ constraints.add(relation.super_type.name, sub_type: relation.sub_type)
183
+ success(constraints: constraints)
184
+
185
+ when relation.sub_type.is_a?(AST::Types::Var) && constraints.unknown?(relation.sub_type.name)
186
+ constraints.add(relation.sub_type.name, super_type: relation.super_type)
187
+ success(constraints: constraints)
191
188
 
192
189
  when relation.sub_type.is_a?(AST::Types::Union)
193
190
  results = relation.sub_type.types.map do |sub_type|
@@ -241,14 +238,6 @@ module Steep
241
238
  results.find(&:failure?)
242
239
  end
243
240
 
244
- when relation.super_type.is_a?(AST::Types::Var) && constraints.unknown?(relation.super_type.name)
245
- constraints.add(relation.super_type.name, sub_type: relation.sub_type)
246
- success(constraints: constraints)
247
-
248
- when relation.sub_type.is_a?(AST::Types::Var) && constraints.unknown?(relation.sub_type.name)
249
- constraints.add(relation.sub_type.name, super_type: relation.super_type)
250
- success(constraints: constraints)
251
-
252
241
  when relation.super_type.is_a?(AST::Types::Var) || relation.sub_type.is_a?(AST::Types::Var)
253
242
  failure(error: Result::Failure::UnknownPairError.new(relation: relation),
254
243
  trace: trace)
@@ -275,7 +264,7 @@ module Steep
275
264
  possible_sub_types = case relation.sub_type
276
265
  when AST::Types::Name::Instance
277
266
  instance_super_types(relation.sub_type.name, args: relation.sub_type.args)
278
- when AST::Types::Name::Class
267
+ when AST::Types::Name::Singleton
279
268
  singleton_super_types(relation.sub_type.name)
280
269
  else
281
270
  []
@@ -311,10 +300,9 @@ module Steep
311
300
  when relation.sub_type.is_a?(AST::Types::Tuple) && relation.super_type.is_a?(AST::Types::Tuple)
312
301
  if relation.sub_type.types.size >= relation.super_type.types.size
313
302
  pairs = relation.sub_type.types.take(relation.super_type.types.size).zip(relation.super_type.types)
314
- results = pairs.flat_map do |t1, t2|
303
+ results = pairs.map do |t1, t2|
315
304
  relation = Relation.new(sub_type: t1, super_type: t2)
316
- [check(relation, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints),
317
- check(relation.flip, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)]
305
+ check(relation, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)
318
306
  end
319
307
 
320
308
  if results.all?(&:success?)
@@ -327,16 +315,17 @@ module Steep
327
315
  trace: trace)
328
316
  end
329
317
 
330
- when relation.sub_type.is_a?(AST::Types::Tuple) && relation.super_type.is_a?(AST::Types::Name::Base)
331
- tuple_interface = factory.interface(relation.sub_type, private: false)
332
- type_interface = factory.interface(relation.super_type, private: false)
318
+ when relation.sub_type.is_a?(AST::Types::Tuple) && AST::Builtin::Array.instance_type?(relation.super_type)
319
+ tuple_element_type = AST::Types::Union.build(
320
+ types: relation.sub_type.types,
321
+ location: relation.sub_type.location
322
+ )
333
323
 
334
- check_interface(tuple_interface,
335
- type_interface,
336
- self_type: self_type,
337
- assumption: assumption,
338
- trace: trace,
339
- constraints: constraints)
324
+ check(Relation.new(sub_type: tuple_element_type, super_type: relation.super_type.args[0]),
325
+ self_type: self_type,
326
+ assumption: assumption,
327
+ trace: trace,
328
+ constraints: constraints)
340
329
 
341
330
  when relation.sub_type.is_a?(AST::Types::Record) && relation.super_type.is_a?(AST::Types::Record)
342
331
  if Set.new(relation.sub_type.elements.keys).superset?(Set.new(relation.super_type.elements.keys))
@@ -386,6 +375,15 @@ module Steep
386
375
  when relation.sub_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.super_type)
387
376
  success(constraints: constraints)
388
377
 
378
+ when relation.sub_type.is_a?(AST::Types::Literal)
379
+ check(
380
+ Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type),
381
+ self_type: self_type,
382
+ assumption: assumption,
383
+ trace: trace,
384
+ constraints: constraints
385
+ )
386
+
389
387
  else
390
388
  failure(error: Result::Failure::UnknownPairError.new(relation: relation),
391
389
  trace: trace)
@@ -399,7 +397,7 @@ module Steep
399
397
  case type
400
398
  when AST::Types::Name::Instance
401
399
  factory.definition_builder.build_instance(type_name)
402
- when AST::Types::Name::Class
400
+ when AST::Types::Name::Singleton
403
401
  factory.definition_builder.build_singleton(type_name)
404
402
  when AST::Types::Name::Interface
405
403
  factory.definition_builder.build_interface(type_name)
@@ -484,11 +482,7 @@ module Steep
484
482
  if sub_type.name == super_type.name && sub_type.args.size == super_type.args.size
485
483
  sub_type.args.zip(super_type.args)
486
484
  end
487
- when sub_type.is_a?(AST::Types::Name::Class) && super_type.is_a?(AST::Types::Name::Class)
488
- if sub_type.name == super_type.name
489
- []
490
- end
491
- when sub_type.is_a?(AST::Types::Name::Module) && super_type.is_a?(AST::Types::Name::Module)
485
+ when sub_type.is_a?(AST::Types::Name::Singleton) && super_type.is_a?(AST::Types::Name::Singleton)
492
486
  if sub_type.name == super_type.name
493
487
  []
494
488
  end
@@ -535,29 +529,24 @@ module Steep
535
529
 
536
530
  def check_method(name, sub_method, super_method, self_type:, assumption:, trace:, constraints:)
537
531
  trace.method name, sub_method, super_method do
538
- case
539
- when sub_method.overload? && super_method.overload?
540
- super_method.types.map do |super_type|
541
- sub_method.types.map do |sub_type|
542
- check_generic_method_type name,
543
- sub_type,
544
- super_type,
545
- self_type: self_type,
546
- assumption: assumption,
547
- trace: trace,
548
- constraints: constraints
549
- end.yield_self do |results|
550
- results.find(&:success?) || results[0]
551
- end
532
+ super_method.method_types.map do |super_type|
533
+ sub_method.method_types.map do |sub_type|
534
+ check_generic_method_type name,
535
+ sub_type,
536
+ super_type,
537
+ self_type: self_type,
538
+ assumption: assumption,
539
+ trace: trace,
540
+ constraints: constraints
552
541
  end.yield_self do |results|
553
- if results.all?(&:success?) || sub_method.incompatible?
554
- success constraints: constraints
555
- else
556
- results.select(&:failure?).last
557
- end
542
+ results.find(&:success?) || results[0]
543
+ end
544
+ end.yield_self do |results|
545
+ if results.all?(&:success?)
546
+ success constraints: constraints
547
+ else
548
+ results.select(&:failure?).last
558
549
  end
559
- else
560
- raise "aaaaaaaaaaaaaa"
561
550
  end
562
551
  end
563
552
  end
@@ -113,6 +113,7 @@ module Steep
113
113
  end
114
114
 
115
115
  def check_relation(sub_type:, super_type:, constraints: Subtyping::Constraints.empty)
116
+ Steep.logger.debug { "check_relation: self:#{self_type} |- #{sub_type} <: #{super_type}" }
116
117
  checker.check(Subtyping::Relation.new(sub_type: sub_type, super_type: super_type), self_type: self_type, constraints: constraints)
117
118
  end
118
119
 
@@ -286,7 +287,6 @@ module Steep
286
287
 
287
288
  instance_type = AST::Types::Intersection.build(
288
289
  types: [
289
- AST::Types::Name::Instance.new(name: module_name, args: module_args),
290
290
  AST::Builtin::Object.instance_type,
291
291
  *module_entry.self_types.map {|module_self|
292
292
  type = case
@@ -304,11 +304,12 @@ module Steep
304
304
  )
305
305
  end
306
306
  checker.factory.type(type)
307
- }
307
+ },
308
+ AST::Types::Name::Instance.new(name: module_name, args: module_args)
308
309
  ].compact
309
310
  )
310
311
 
311
- module_type = AST::Types::Name::Class.new(name: module_name, constructor: nil)
312
+ module_type = AST::Types::Name::Singleton.new(name: module_name)
312
313
  end
313
314
 
314
315
  if annots.instance_type
@@ -379,7 +380,7 @@ module Steep
379
380
  module_def = checker.factory.definition_builder.build_singleton(type_name_)
380
381
 
381
382
  instance_type = AST::Types::Name::Instance.new(name: class_name, args: class_args)
382
- module_type = AST::Types::Name::Class.new(name: class_name, constructor: nil)
383
+ module_type = AST::Types::Name::Singleton.new(name: class_name)
383
384
  end
384
385
 
385
386
  if annots.instance_type
@@ -443,18 +444,26 @@ module Steep
443
444
  end
444
445
 
445
446
  module_type = case instance_type
446
- when AST::Types::Name::Class
447
- AST::Builtin::Class.instance_type
448
- when AST::Types::Name::Module
449
- AST::Builtin::Module.instance_type
447
+ when AST::Types::Name::Singleton
448
+ type_name = checker.factory.type_name_1(instance_type.name)
449
+
450
+ case checker.factory.env.class_decls[type_name]
451
+ when RBS::Environment::ModuleEntry
452
+ AST::Builtin::Module.instance_type
453
+ when RBS::Environment::ClassEntry
454
+ AST::Builtin::Class.instance_type
455
+ else
456
+ raise
457
+ end
458
+
450
459
  when AST::Types::Name::Instance
451
- instance_type.to_class(constructor: nil)
460
+ instance_type.to_module
452
461
  else
453
- raise "Unexpected type for sclass node: #{type}"
462
+ return
454
463
  end
455
464
 
456
465
  instance_definition = case instance_type
457
- when AST::Types::Name::Class, AST::Types::Name::Module
466
+ when AST::Types::Name::Singleton
458
467
  type_name = checker.factory.type_name_1(instance_type.name)
459
468
  checker.factory.definition_builder.build_singleton(type_name)
460
469
  when AST::Types::Name::Instance
@@ -463,7 +472,7 @@ module Steep
463
472
  end
464
473
 
465
474
  module_definition = case module_type
466
- when AST::Types::Name::Class, AST::Types::Name::Module
475
+ when AST::Types::Name::Singleton
467
476
  type_name = checker.factory.type_name_1(instance_type.name)
468
477
  checker.factory.definition_builder.build_singleton(type_name)
469
478
  else
@@ -638,7 +647,11 @@ module Steep
638
647
  when :__skip__
639
648
  add_typing(node, type: AST::Builtin.any_type)
640
649
  else
641
- rhs_result = synthesize(rhs, hint: hint || context.lvar_env.declared_types[name]&.type)
650
+ if !hint || hint.is_a?(AST::Types::Void)
651
+ hint = context.lvar_env.declared_types[name]&.type
652
+ end
653
+
654
+ rhs_result = synthesize(rhs, hint: hint)
642
655
 
643
656
  constr = rhs_result.constr.update_lvar_env do |lvar_env|
644
657
  lvar_env.assign(name, node: node, type: rhs_result.type) do |declared_type, actual_type, result|
@@ -682,8 +695,8 @@ module Steep
682
695
  yield_self do
683
696
  if self_class?(node)
684
697
  module_type = expand_alias(module_context.module_type)
685
- type = if module_type.is_a?(AST::Types::Name::Class)
686
- AST::Types::Name::Class.new(name: module_type.name, constructor: method_context.constructor)
698
+ type = if module_type.is_a?(AST::Types::Name::Singleton)
699
+ AST::Types::Name::Singleton.new(name: module_type.name)
687
700
  else
688
701
  module_type
689
702
  end
@@ -698,8 +711,8 @@ module Steep
698
711
  yield_self do
699
712
  pair = if self_class?(node)
700
713
  module_type = expand_alias(module_context.module_type)
701
- type = if module_type.is_a?(AST::Types::Name::Class)
702
- AST::Types::Name::Class.new(name: module_type.name, constructor: method_context.constructor)
714
+ type = if module_type.is_a?(AST::Types::Name::Singleton)
715
+ AST::Types::Name::Singleton.new(name: module_type.name)
703
716
  else
704
717
  module_type
705
718
  end
@@ -743,6 +756,23 @@ module Steep
743
756
 
744
757
  constr.add_typing(node, type: type)
745
758
 
759
+ when :cvasgn
760
+ var_node = lhs.updated(:cvar)
761
+ send_node = rhs.updated(:send, [var_node, op, rhs])
762
+ new_node = node.updated(:cvasgn, [lhs.children[0], send_node])
763
+
764
+ type, constr = synthesize(new_node, hint: hint)
765
+
766
+ constr.add_typing(node, type: type)
767
+
768
+ when :send
769
+ new_rhs = rhs.updated(:send, [lhs, node.children[1], node.children[2]])
770
+ new_node = lhs.updated(:send, [lhs.children[0], :"#{lhs.children[1]}=", *lhs.children.drop(2), new_rhs])
771
+
772
+ type, constr = synthesize(new_node, hint: hint)
773
+
774
+ constr.add_typing(node, type: type)
775
+
746
776
  else
747
777
  Steep.logger.error("Unexpected op_asgn lhs: #{lhs.type}")
748
778
 
@@ -759,11 +789,10 @@ module Steep
759
789
  synthesize(child)
760
790
  end
761
791
 
762
- super_method = Interface::Interface::Combination.overload(
763
- method_context.super_method.method_types.map {|method_type|
792
+ super_method = Interface::Interface::Entry.new(
793
+ method_types: method_context.super_method.method_types.map {|method_type|
764
794
  checker.factory.method_type(method_type, self_type: self_type)
765
- },
766
- incompatible: false
795
+ }
767
796
  )
768
797
  args = TypeInference::SendArgs.from_nodes(node.children.dup)
769
798
 
@@ -810,7 +839,7 @@ module Steep
810
839
  new.typing.add_context_for_body(node, context: new.context)
811
840
 
812
841
  each_child_node(args_node) do |arg|
813
- new.synthesize(arg)
842
+ _, new = new.synthesize(arg)
814
843
  end
815
844
 
816
845
  body_pair = if body_node
@@ -861,7 +890,7 @@ module Steep
861
890
  when AST::Types::Name::Instance
862
891
  name = checker.factory.type_name_1(self_type.name)
863
892
  checker.factory.definition_builder.build_singleton(name)
864
- when AST::Types::Name::Module, AST::Types::Name::Class
893
+ when AST::Types::Name::Singleton
865
894
  name = checker.factory.type_name_1(self_type.name)
866
895
  checker.factory.definition_builder.build_singleton(name)
867
896
  end
@@ -998,11 +1027,17 @@ module Steep
998
1027
  yield_self do
999
1028
  var = node.children[0]
1000
1029
  type = context.lvar_env[var.name]
1001
- unless type
1030
+
1031
+ if type
1032
+ add_typing(node, type: type)
1033
+ else
1002
1034
  type = AST::Builtin.any_type
1003
- Steep.logger.error { "Unknown arg type: #{node}" }
1035
+ if context&.method_context&.method_type
1036
+ Steep.logger.error { "Unknown arg type: #{node}" }
1037
+ end
1038
+
1039
+ lvasgn(node, type)
1004
1040
  end
1005
- add_typing(node, type: type)
1006
1041
  end
1007
1042
 
1008
1043
  when :optarg, :kwoptarg
@@ -1010,12 +1045,13 @@ module Steep
1010
1045
  var = node.children[0]
1011
1046
  rhs = node.children[1]
1012
1047
 
1013
- type = context.lvar_env[var.name]
1048
+ var_type = context.lvar_env[var.name]
1049
+ node_type, constr = synthesize(rhs, hint: var_type)
1014
1050
 
1015
- node_type, constr = synthesize(rhs, hint: type)
1051
+ type = AST::Types::Union.build(types: [var_type, node_type])
1016
1052
 
1017
1053
  constr_ = constr.update_lvar_env do |env|
1018
- env.assign(var.name, node: node, type: node_type) do |declared_type, type, result|
1054
+ env.assign(var.name, node: node, type: type) do |declared_type, type, result|
1019
1055
  typing.add_error(
1020
1056
  Errors::IncompatibleAssignment.new(node: node,
1021
1057
  lhs_type: declared_type,
@@ -1025,7 +1061,7 @@ module Steep
1025
1061
  end
1026
1062
  end
1027
1063
 
1028
- add_typing(node, type: constr_.context.lvar_env[var.name], constr: constr_)
1064
+ add_typing(node, type: type, constr: constr_)
1029
1065
  end
1030
1066
 
1031
1067
  when :restarg
@@ -1033,7 +1069,9 @@ module Steep
1033
1069
  var = node.children[0]
1034
1070
  type = context.lvar_env[var.name]
1035
1071
  unless type
1036
- Steep.logger.error { "Unknown variable: #{node}" }
1072
+ if context&.method_context&.method_type
1073
+ Steep.logger.error { "Unknown variable: #{node}" }
1074
+ end
1037
1075
  typing.add_error Errors::FallbackAny.new(node: node)
1038
1076
  type = AST::Builtin::Array.instance_type(AST::Builtin.any_type)
1039
1077
  end
@@ -1046,7 +1084,9 @@ module Steep
1046
1084
  var = node.children[0]
1047
1085
  type = context.lvar_env[var.name]
1048
1086
  unless type
1049
- Steep.logger.error { "Unknown variable: #{node}" }
1087
+ if context&.method_context&.method_type
1088
+ Steep.logger.error { "Unknown variable: #{node}" }
1089
+ end
1050
1090
  typing.add_error Errors::FallbackAny.new(node: node)
1051
1091
  type = AST::Builtin::Hash.instance_type(AST::Builtin::Symbol.instance_type, AST::Builtin.any_type)
1052
1092
  end
@@ -1062,7 +1102,7 @@ module Steep
1062
1102
 
1063
1103
  when :int
1064
1104
  yield_self do
1065
- literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
1105
+ literal_type = test_literal_type(node.children[0], hint)
1066
1106
 
1067
1107
  if literal_type
1068
1108
  add_typing(node, type: literal_type)
@@ -1073,7 +1113,7 @@ module Steep
1073
1113
 
1074
1114
  when :sym
1075
1115
  yield_self do
1076
- literal_type = expand_alias(hint) {|hint| test_literal_type(node.children[0], hint) }
1116
+ literal_type = test_literal_type(node.children[0], hint)
1077
1117
 
1078
1118
  if literal_type
1079
1119
  add_typing(node, type: literal_type)
@@ -1084,7 +1124,7 @@ module Steep
1084
1124
 
1085
1125
  when :str
1086
1126
  yield_self do
1087
- literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_)}
1127
+ literal_type = test_literal_type(node.children[0], hint)
1088
1128
 
1089
1129
  if literal_type
1090
1130
  add_typing(node, type: literal_type)
@@ -1201,6 +1241,17 @@ module Steep
1201
1241
  type, constr = synthesize(node.children[0])
1202
1242
  constructor = constr.for_sclass(node, type)
1203
1243
 
1244
+ unless constructor
1245
+ typing.add_error(
1246
+ Errors::UnsupportedSyntax.new(
1247
+ node: node,
1248
+ message: "sclass receiver must be instance type or singleton type, but type given `#{type}`"
1249
+ )
1250
+ )
1251
+ constr.add_typing(node, type: AST::Builtin.nil_type)
1252
+ return
1253
+ end
1254
+
1204
1255
  constructor.typing.add_context_for_node(node, context: constructor.context)
1205
1256
  constructor.typing.add_context_for_body(node, context: constructor.context)
1206
1257
 
@@ -1212,7 +1263,7 @@ module Steep
1212
1263
  end
1213
1264
  end
1214
1265
 
1215
- add_typing(node, type: AST::Builtin.nil_type)
1266
+ constr.add_typing(node, type: AST::Builtin.nil_type)
1216
1267
  end
1217
1268
 
1218
1269
  when :self
@@ -1300,69 +1351,45 @@ module Steep
1300
1351
  when :array
1301
1352
  yield_self do
1302
1353
  if node.children.empty?
1303
- typing.add_error Errors::FallbackAny.new(node: node) unless hint
1304
-
1305
- array_type = if hint
1306
- if check_relation(sub_type: AST::Builtin::Array.instance_type(AST::Builtin.any_type),
1307
- super_type: hint).success?
1308
- hint
1309
- end
1310
- end
1311
-
1312
- add_typing(node, type: array_type || AST::Builtin::Array.instance_type(AST::Builtin.any_type))
1313
- else
1314
- is_tuple = nil
1315
-
1316
- expand_alias(hint) do |hint|
1317
- is_tuple = hint.is_a?(AST::Types::Tuple)
1318
- is_tuple &&= node.children.all? {|child| child.type != :splat}
1319
- is_tuple &&= node.children.size >= hint.types.size
1320
- is_tuple &&= hint.types.map.with_index do |child_type, index|
1321
- child_node = node.children[index]
1322
- [synthesize(child_node, hint: child_type).type, child_type]
1323
- end.all? do |node_type, hint_type|
1324
- result = check_relation(sub_type: node_type, super_type: hint_type)
1325
- result.success?
1354
+ if hint
1355
+ array = AST::Builtin::Array.instance_type(AST::Builtin.any_type)
1356
+ if check_relation(sub_type: array, super_type: hint).success?
1357
+ add_typing node, type: hint
1358
+ else
1359
+ add_typing node, type: array
1326
1360
  end
1327
- end
1328
-
1329
- if is_tuple
1330
- array_type = hint
1331
1361
  else
1332
- element_hint = expand_alias(hint) do |hint|
1333
- AST::Builtin::Array.instance_type?(hint) && hint.args[0]
1362
+ typing.add_error Errors::FallbackAny.new(node: node)
1363
+ add_typing node, type: AST::Builtin::Array.instance_type(AST::Builtin.any_type)
1364
+ end
1365
+ else
1366
+ node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
1367
+
1368
+ if hint && !(tuples = select_flatten_types(hint) {|type| type.is_a?(AST::Types::Tuple) }).empty?
1369
+ tuples.each do |tuple|
1370
+ typing.new_child(node_range) do |child_typing|
1371
+ pair = with_new_typing(child_typing).try_tuple_type(node, tuple)
1372
+ if pair && pair.constr.check_relation(sub_type: pair.type, super_type: hint).success?
1373
+ child_typing.save!
1374
+ return pair.with(constr: pair.constr.with_new_typing(typing))
1375
+ end
1376
+ end
1334
1377
  end
1378
+ end
1335
1379
 
1336
- element_types = node.children.flat_map do |e|
1337
- if e.type == :splat
1338
- Steep.logger.info "Typing of splat in array is incompatible with Ruby; it does not use #to_a method"
1339
- synthesize(e.children.first).type.yield_self do |type|
1340
- expand_alias(type) do |ty|
1341
- case ty
1342
- when AST::Types::Union
1343
- ty.types
1344
- else
1345
- [ty]
1346
- end
1347
- end
1348
- end.map do |type|
1349
- case
1350
- when AST::Builtin::Array.instance_type?(type)
1351
- type.args.first
1352
- when AST::Builtin::Range.instance_type?(type)
1353
- type.args.first
1354
- else
1355
- type
1356
- end
1380
+ if hint && !(arrays = select_flatten_types(hint) {|type| AST::Builtin::Array.instance_type?(type) }).empty?
1381
+ arrays.each do |array|
1382
+ typing.new_child(node_range) do |child_typing|
1383
+ pair = with_new_typing(child_typing).try_array_type(node, array)
1384
+ if pair.constr.check_relation(sub_type: pair.type, super_type: hint).success?
1385
+ child_typing.save!
1386
+ return pair.with(constr: pair.constr.with_new_typing(typing))
1357
1387
  end
1358
- else
1359
- [select_super_type(synthesize(e, hint: element_hint).type, element_hint)]
1360
1388
  end
1361
1389
  end
1362
- array_type = AST::Builtin::Array.instance_type(AST::Types::Union.build(types: element_types))
1363
1390
  end
1364
1391
 
1365
- add_typing(node, type: array_type)
1392
+ try_array_type(node, nil)
1366
1393
  end
1367
1394
  end
1368
1395
 
@@ -1505,38 +1532,53 @@ module Steep
1505
1532
  test_types << expand_alias(type)
1506
1533
  end
1507
1534
 
1508
- if body
1509
- if var_names && var_types && test_types.all? {|ty| ty.is_a?(AST::Types::Name::Class) }
1510
- var_types_in_body = test_types.flat_map do |test_type|
1511
- filtered_types = var_types.select do |var_type|
1512
- var_type.is_a?(AST::Types::Name::Base) && var_type.name == test_type.name
1513
- end
1514
- if filtered_types.empty?
1515
- to_instance_type(test_type)
1516
- else
1517
- filtered_types
1518
- end
1535
+ if var_names && var_types && test_types.all? {|ty| ty.is_a?(AST::Types::Name::Singleton) }
1536
+ var_types_in_body = test_types.flat_map do |test_type|
1537
+ filtered_types = var_types.select do |var_type|
1538
+ var_type.is_a?(AST::Types::Name::Base) && var_type.name == test_type.name
1519
1539
  end
1520
-
1521
- var_types.reject! do |type|
1522
- var_types_in_body.any? do |test_type|
1523
- type.is_a?(AST::Types::Name::Base) && test_type.name == type.name
1524
- end
1540
+ if filtered_types.empty?
1541
+ to_instance_type(test_type)
1542
+ else
1543
+ filtered_types
1525
1544
  end
1545
+ end
1526
1546
 
1527
- var_type_in_body = union_type(*var_types_in_body)
1528
- type_case_override = var_names.each.with_object({}) do |var_name, hash|
1529
- hash[var_name] = var_type_in_body
1547
+ var_types.reject! do |type|
1548
+ var_types_in_body.any? do |test_type|
1549
+ type.is_a?(AST::Types::Name::Base) && test_type.name == type.name
1530
1550
  end
1551
+ end
1552
+
1553
+ var_type_in_body = union_type(*var_types_in_body)
1554
+ type_case_override = var_names.each.with_object({}) do |var_name, hash|
1555
+ hash[var_name] = var_type_in_body
1556
+ end
1531
1557
 
1558
+ if body
1532
1559
  branch_pairs << clause_constr
1533
1560
  .for_branch(body, type_case_override: type_case_override)
1534
1561
  .synthesize(body, hint: hint)
1535
1562
  else
1536
- branch_pairs << clause_constr.synthesize(body, hint: hint)
1563
+ branch_pairs << Pair.new(type: AST::Builtin.nil_type, constr: clause_constr)
1537
1564
  end
1538
1565
  else
1539
- branch_pairs << Pair.new(type: AST::Builtin.nil_type, constr: clause_constr)
1566
+ logic = TypeInference::Logic.new(subtyping: checker)
1567
+
1568
+ truthys, falseys = logic.nodes(node: ::AST::Node.new(:begin, tests))
1569
+ truthy_env, _ = logic.environments(truthy_vars: truthys.vars,
1570
+ falsey_vars: falseys.vars,
1571
+ lvar_env: clause_constr.context.lvar_env)
1572
+
1573
+ if body
1574
+ branch_pairs << constr
1575
+ .update_lvar_env { truthy_env }
1576
+ .for_branch(body)
1577
+ .tap {|constr| typing.add_context_for_node(body, context: constr.context) }
1578
+ .synthesize(body, hint: hint)
1579
+ else
1580
+ branch_pairs << Pair.new(type: AST::Builtin.nil_type, constr: clause_constr)
1581
+ end
1540
1582
  end
1541
1583
  end
1542
1584
 
@@ -1616,7 +1658,7 @@ module Steep
1616
1658
  instance_types = exn_types.map do |type|
1617
1659
  type = expand_alias(type)
1618
1660
  case
1619
- when type.is_a?(AST::Types::Name::Class)
1661
+ when type.is_a?(AST::Types::Name::Singleton)
1620
1662
  to_instance_type(type)
1621
1663
  else
1622
1664
  AST::Builtin.any_type
@@ -1671,6 +1713,49 @@ module Steep
1671
1713
  when :masgn
1672
1714
  type_masgn(node)
1673
1715
 
1716
+ when :for
1717
+ yield_self do
1718
+ asgn, collection, body = node.children
1719
+
1720
+ collection_type, constr = synthesize(collection)
1721
+ collection_type = expand_self(collection_type)
1722
+
1723
+ var_type = case collection_type
1724
+ when AST::Types::Any
1725
+ AST::Types::Any.new
1726
+ else
1727
+ each = checker.factory.interface(collection_type, private: true).methods[:each]
1728
+ method_type = (each&.method_types || []).find {|type| type.block && type.block.type.params.first_param }
1729
+ method_type&.yield_self do |method_type|
1730
+ method_type.block.type.params.first_param&.type
1731
+ end
1732
+ end
1733
+
1734
+ if var_type
1735
+ if body
1736
+ body_constr = constr.with_updated_context(
1737
+ lvar_env: constr.context.lvar_env.assign(asgn.children[0].name, node: asgn, type: var_type)
1738
+ )
1739
+
1740
+ typing.add_context_for_body(node, context: body_constr.context)
1741
+ _, _, body_context = body_constr.synthesize(body)
1742
+
1743
+ constr = constr.update_lvar_env {|env| env.join(constr.context.lvar_env, body_context.lvar_env) }
1744
+ else
1745
+ constr = self
1746
+ end
1747
+
1748
+ add_typing(node, type: collection_type, constr: constr)
1749
+ else
1750
+ fallback_to_any(node) do
1751
+ Errors::NoMethod.new(
1752
+ node: node,
1753
+ method: :each,
1754
+ type: collection_type
1755
+ )
1756
+ end
1757
+ end
1758
+ end
1674
1759
  when :while, :until
1675
1760
  yield_self do
1676
1761
  cond, body = node.children
@@ -1732,9 +1817,22 @@ module Steep
1732
1817
  end
1733
1818
 
1734
1819
  when :irange, :erange
1735
- types = node.children.map {|n| synthesize(n).type }
1736
- type = AST::Builtin::Range.instance_type(union_type(*types))
1737
- add_typing(node, type: type)
1820
+ begin_node, end_node = node.children
1821
+
1822
+ constr = self
1823
+ begin_type, constr = if begin_node
1824
+ constr.synthesize(begin_node)
1825
+ else
1826
+ [AST::Builtin.nil_type, constr]
1827
+ end
1828
+ end_type, constr = if end_node
1829
+ constr.synthesize(end_node)
1830
+ else
1831
+ [AST::Builtin.nil_type, constr]
1832
+ end
1833
+
1834
+ type = AST::Builtin::Range.instance_type(union_type(begin_type, end_type))
1835
+ add_typing(node, type: type, constr: constr)
1738
1836
 
1739
1837
  when :regexp
1740
1838
  each_child_node(node) do |child|
@@ -1752,9 +1850,36 @@ module Steep
1752
1850
 
1753
1851
  when :or_asgn, :and_asgn
1754
1852
  yield_self do
1755
- _, rhs = node.children
1756
- rhs_type = synthesize(rhs).type
1757
- add_typing(node, type: rhs_type)
1853
+ asgn, rhs = node.children
1854
+
1855
+ case asgn.type
1856
+ when :lvasgn
1857
+ type, constr = synthesize(rhs, hint: hint)
1858
+ constr.lvasgn(asgn, type)
1859
+ when :ivasgn
1860
+ type, constr = synthesize(rhs, hint: hint)
1861
+ constr.ivasgn(asgn, type)
1862
+ when :send
1863
+ rhs_ = node.updated(:send,
1864
+ [
1865
+ asgn.children[0],
1866
+ :"#{asgn.children[1]}=",
1867
+ asgn.children[2],
1868
+ rhs
1869
+ ])
1870
+ node_type = case node.type
1871
+ when :or_asgn
1872
+ :or
1873
+ when :and_asgn
1874
+ :and
1875
+ end
1876
+ node_ = node.updated(node_type, [asgn, rhs_])
1877
+
1878
+ synthesize(node_, hint: hint)
1879
+ else
1880
+ Steep.logger.error { "#{node.type} with #{asgn.type} lhs is not supported"}
1881
+ fallback_to_any(node)
1882
+ end
1758
1883
  end
1759
1884
 
1760
1885
  when :defined?
@@ -1801,8 +1926,8 @@ module Steep
1801
1926
  param_type = hint.params.required[0]
1802
1927
  interface = checker.factory.interface(param_type, private: true)
1803
1928
  method = interface.methods[value.children[0]]
1804
- if method&.overload?
1805
- return_types = method.types.select {|method_type|
1929
+ if method
1930
+ return_types = method.method_types.select {|method_type|
1806
1931
  method_type.params.each_type.count == 0
1807
1932
  }.map(&:return_type)
1808
1933
 
@@ -1830,9 +1955,50 @@ module Steep
1830
1955
  add_typing node, type: AST::Builtin.any_type
1831
1956
  end
1832
1957
 
1833
- when :splat, :sclass, :alias
1958
+ when :cvasgn
1959
+ name, rhs = node.children
1960
+
1961
+ type, constr = synthesize(rhs, hint: hint)
1962
+
1963
+ var_type = if module_context&.class_variables
1964
+ module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
1965
+ end
1966
+
1967
+ if var_type
1968
+ result = constr.check_relation(sub_type: type, super_type: var_type)
1969
+
1970
+ if result.success?
1971
+ add_typing node, type: type, constr: constr
1972
+ else
1973
+ fallback_to_any node do
1974
+ Errors::IncompatibleAssignment.new(node: node,
1975
+ lhs_type: var_type,
1976
+ rhs_type: type,
1977
+ result: result)
1978
+ end
1979
+ end
1980
+ else
1981
+ fallback_to_any(node)
1982
+ end
1983
+
1984
+ when :cvar
1985
+ name = node.children[0]
1986
+ var_type = if module_context&.class_variables
1987
+ module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
1988
+ end
1989
+
1990
+ if var_type
1991
+ add_typing node, type: var_type
1992
+ else
1993
+ fallback_to_any node
1994
+ end
1995
+
1996
+ when :alias
1997
+ add_typing node, type: AST::Builtin.nil_type
1998
+
1999
+ when :splat
1834
2000
  yield_self do
1835
- Steep.logger.error "Unsupported node #{node.type} (#{node.location.expression.source_buffer.name}:#{node.location.expression.line})"
2001
+ Steep.logger.warn { "Unsupported node #{node.type} (#{node.location.expression.source_buffer.name}:#{node.location.expression.line})" }
1836
2002
 
1837
2003
  each_child_node node do |child|
1838
2004
  synthesize(child)
@@ -1882,136 +2048,202 @@ module Steep
1882
2048
  add_typing(node, type: ivar_type)
1883
2049
  end
1884
2050
 
2051
+ def masgn_lhs?(lhs)
2052
+ lhs.children.all? do |a|
2053
+ asgn_type = if a.type == :splat
2054
+ a.children[0].type
2055
+ else
2056
+ a.type
2057
+ end
2058
+ asgn_type == :lvasgn || asgn_type == :ivasgn
2059
+ end
2060
+ end
2061
+
2062
+ def lvasgn(node, type)
2063
+ name = node.children[0].name
2064
+ env = context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
2065
+ typing.add_error(
2066
+ Errors::IncompatibleAssignment.new(node: node,
2067
+ lhs_type: declared_type,
2068
+ rhs_type: type,
2069
+ result: result)
2070
+ )
2071
+ end
2072
+
2073
+ add_typing(node, type: type, constr: with_updated_context(lvar_env: env))
2074
+ end
2075
+
2076
+ def ivasgn(node, type)
2077
+ ivar = node.children[0]
2078
+
2079
+ type_env.assign(ivar: ivar, type: type, self_type: self_type) do |error|
2080
+ case error
2081
+ when Subtyping::Result::Failure
2082
+ var_type = type_env.get(ivar: ivar)
2083
+ typing.add_error(Errors::IncompatibleAssignment.new(node: node,
2084
+ lhs_type: var_type,
2085
+ rhs_type: type,
2086
+ result: error))
2087
+ when nil
2088
+ fallback_to_any node
2089
+ end
2090
+ end
2091
+
2092
+ add_typing(node, type: type)
2093
+ end
2094
+
1885
2095
  def type_masgn(node)
1886
2096
  lhs, rhs = node.children
1887
2097
  rhs_pair = synthesize(rhs)
1888
- rhs_type = expand_alias(rhs_pair.type)
2098
+ rhs_type = deep_expand_alias(rhs_pair.type)
1889
2099
 
1890
2100
  constr = rhs_pair.constr
1891
2101
 
1892
- if lhs.children.all? {|a| a.type == :lvasgn || a.type == :ivasgn}
1893
- case
1894
- when rhs.type == :array && lhs.children.size == rhs.children.size
1895
- # a, @b = x, y
2102
+ unless masgn_lhs?(lhs)
2103
+ Steep.logger.error("Unsupported masgn lhs node: only lvasgn, ivasgn, and splat are supported")
2104
+ _, constr = constr.fallback_to_any(lhs)
2105
+ return add_typing(node, type: rhs_type, constr: constr)
2106
+ end
1896
2107
 
1897
- constr = lhs.children.zip(rhs.children).inject(constr) do |ctr, (lhs, rhs)|
1898
- case lhs.type
1899
- when :lvasgn
1900
- name = lhs.children[0].name
1901
- type = typing.type_of(node: rhs)
1902
- env = ctr.context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
1903
- typing.add_error(
1904
- Errors::IncompatibleAssignment.new(node: lhs,
1905
- lhs_type: declared_type,
1906
- rhs_type: type,
1907
- result: result)
1908
- )
1909
- end
1910
- add_typing(lhs,
1911
- type: type,
1912
- constr: ctr.with_updated_context(lvar_env: env))
1913
- when :ivasgn
1914
- type_ivasgn(lhs.children.first, rhs, lhs)
1915
- constr
1916
- end
2108
+ falseys, truthys = partition_flatten_types(rhs_type) do |type|
2109
+ type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
2110
+ end
2111
+
2112
+ unwrap_rhs_type = AST::Types::Union.build(types: truthys)
2113
+
2114
+ case
2115
+ when unwrap_rhs_type.is_a?(AST::Types::Tuple) || (rhs.type == :array && rhs.children.none? {|n| n.type == :splat })
2116
+ tuple_types = if unwrap_rhs_type.is_a?(AST::Types::Tuple)
2117
+ unwrap_rhs_type.types.dup
2118
+ else
2119
+ rhs.children.map do |node|
2120
+ typing.type_of(node: node)
2121
+ end
2122
+ end
2123
+
2124
+ assignment_nodes = lhs.children.dup
2125
+ leading_assignments = []
2126
+ trailing_assignments = []
2127
+
2128
+ until assignment_nodes.empty?
2129
+ cursor = assignment_nodes.first
2130
+
2131
+ if cursor.type == :splat
2132
+ break
2133
+ else
2134
+ leading_assignments << assignment_nodes.shift
1917
2135
  end
2136
+ end
1918
2137
 
1919
- add_typing(node, type: rhs_type, constr: constr)
2138
+ until assignment_nodes.empty?
2139
+ cursor = assignment_nodes.last
1920
2140
 
1921
- when rhs_type.is_a?(AST::Types::Tuple)
1922
- # a, @b = tuple
2141
+ if cursor.type == :splat
2142
+ break
2143
+ else
2144
+ trailing_assignments.unshift assignment_nodes.pop
2145
+ end
2146
+ end
1923
2147
 
1924
- constr = lhs.children.zip(rhs_type.types).inject(constr) do |ctr, (lhs, type)|
1925
- ty = type || AST::Builtin.nil_type
2148
+ leading_assignments.each do |asgn|
2149
+ type = tuple_types.first
1926
2150
 
1927
- case lhs.type
1928
- when :lvasgn
1929
- name = lhs.children[0].name
1930
- env = ctr.context.lvar_env.assign(name, node: node, type: ty) do |declared_type, type, result|
1931
- typing.add_error(
1932
- Errors::IncompatibleAssignment.new(node: lhs,
1933
- lhs_type: declared_type,
1934
- rhs_type: type,
1935
- result: result)
1936
- )
1937
- end
1938
- add_typing(lhs,
1939
- type: ty,
1940
- constr: ctr.with_updated_context(lvar_env: env)).constr
1941
- when :ivasgn
1942
- ivar = lhs.children[0]
2151
+ if type
2152
+ tuple_types.shift
2153
+ else
2154
+ type = AST::Builtin.nil_type
2155
+ end
1943
2156
 
1944
- type_env.assign(ivar: ivar, type: ty, self_type: self_type) do |error|
1945
- case error
1946
- when Subtyping::Result::Failure
1947
- ivar_type = type_env.get(ivar: ivar)
1948
- typing.add_error(Errors::IncompatibleAssignment.new(node: lhs,
1949
- lhs_type: ivar_type,
1950
- rhs_type: ty,
1951
- result: error))
1952
- when nil
1953
- fallback_to_any node
1954
- end
1955
- end
2157
+ case asgn.type
2158
+ when :lvasgn
2159
+ _, constr = constr.lvasgn(asgn, type)
2160
+ when :ivasgn
2161
+ _, constr = constr.ivasgn(asgn, type)
2162
+ end
2163
+ end
1956
2164
 
1957
- ctr
1958
- end
2165
+ trailing_assignments.reverse_each do |asgn|
2166
+ type = tuple_types.last
2167
+
2168
+ if type
2169
+ tuple_types.pop
2170
+ else
2171
+ type = AST::Builtin.nil_type
1959
2172
  end
1960
2173
 
1961
- add_typing(node, type: rhs_type, constr: constr)
2174
+ case asgn.type
2175
+ when :lvasgn
2176
+ _, constr = constr.lvasgn(asgn, type)
2177
+ when :ivasgn
2178
+ _, constr = constr.ivasgn(asgn, type)
2179
+ end
2180
+ end
1962
2181
 
1963
- when AST::Builtin::Array.instance_type?(rhs_type)
1964
- element_type = AST::Types::Union.build(types: [rhs_type.args.first, AST::Builtin.nil_type])
2182
+ element_type = if tuple_types.empty?
2183
+ AST::Builtin.nil_type
2184
+ else
2185
+ AST::Types::Union.build(types: tuple_types)
2186
+ end
2187
+ array_type = AST::Builtin::Array.instance_type(element_type)
1965
2188
 
1966
- constr = lhs.children.inject(constr) do |ctr, assignment|
1967
- case assignment.type
2189
+ assignment_nodes.each do |asgn|
2190
+ case asgn.type
2191
+ when :splat
2192
+ case asgn.children[0].type
1968
2193
  when :lvasgn
1969
- name = assignment.children[0].name
1970
- env = ctr.context.lvar_env.assign(name, node: node, type: element_type) do |declared_type, type, result|
1971
- typing.add_error(
1972
- Errors::IncompatibleAssignment.new(node: assignment,
1973
- lhs_type: declared_type,
1974
- rhs_type: type,
1975
- result: result)
1976
- )
1977
- end
2194
+ _, constr = constr.lvasgn(asgn.children[0], array_type)
2195
+ when :ivasgn
2196
+ _, constr = constr.ivasgn(asgn.children[0], array_type)
2197
+ end
2198
+ when :lvasgn
2199
+ _, constr = constr.lvasgn(asgn, element_type)
2200
+ when :ivasgn
2201
+ _,constr = constr.ivasgn(asgn, element_type)
2202
+ end
2203
+ end
2204
+
2205
+ unless falseys.empty?
2206
+ constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
2207
+ end
1978
2208
 
1979
- add_typing(assignment,
1980
- type: element_type,
1981
- constr: ctr.with_updated_context(lvar_env: env)).constr
2209
+ add_typing(node, type: rhs_type, constr: constr)
1982
2210
 
1983
- when :ivasgn
1984
- ivar = assignment.children[0]
2211
+ when flatten_union(unwrap_rhs_type).all? {|type| AST::Builtin::Array.instance_type?(type) }
2212
+ array_elements = flatten_union(unwrap_rhs_type).map {|type| type.args[0] }
2213
+ element_type = AST::Types::Union.build(types: array_elements + [AST::Builtin.nil_type])
1985
2214
 
1986
- type_env.assign(ivar: ivar, type: element_type, self_type: self_type) do |error|
1987
- case error
1988
- when Subtyping::Result::Failure
1989
- type = type_env.get(ivar: ivar)
1990
- typing.add_error(Errors::IncompatibleAssignment.new(node: assignment,
1991
- lhs_type: type,
1992
- rhs_type: element_type,
1993
- result: error))
1994
- when nil
1995
- fallback_to_any node
1996
- end
1997
- end
2215
+ constr = lhs.children.inject(constr) do |constr, assignment|
2216
+ case assignment.type
2217
+ when :lvasgn
2218
+ _, constr = constr.lvasgn(assignment, element_type)
1998
2219
 
1999
- ctr
2220
+ when :ivasgn
2221
+ _, constr = constr.ivasgn(assignment, element_type)
2222
+ when :splat
2223
+ case assignment.children[0].type
2224
+ when :lvasgn
2225
+ _, constr = constr.lvasgn(assignment.children[0], unwrap_rhs_type)
2226
+ when :ivasgn
2227
+ _, constr = constr.ivasgn(assignment.children[0], unwrap_rhs_type)
2228
+ else
2229
+ raise
2000
2230
  end
2001
2231
  end
2002
2232
 
2003
- add_typing node, type: rhs_type, constr: constr
2004
-
2005
- when rhs_type.is_a?(AST::Types::Any)
2006
- fallback_to_any(node)
2233
+ constr
2234
+ end
2007
2235
 
2008
- else
2009
- Steep.logger.error("Unsupported masgn: #{rhs.type} (#{rhs_type})")
2010
- fallback_to_any(node)
2236
+ unless falseys.empty?
2237
+ constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
2011
2238
  end
2239
+
2240
+ add_typing(node, type: rhs_type, constr: constr)
2012
2241
  else
2013
- Steep.logger.error("Unsupported masgn left hand side")
2014
- fallback_to_any(node)
2242
+ unless rhs_type.is_a?(AST::Types::Any)
2243
+ Steep.logger.error("Unsupported masgn rhs type: array or tuple is supported (#{rhs_type})")
2244
+ end
2245
+ _, constr = constr.fallback_to_any(lhs)
2246
+ add_typing(node, type: rhs_type, constr: constr)
2015
2247
  end
2016
2248
  end
2017
2249
 
@@ -2062,7 +2294,7 @@ module Steep
2062
2294
  else
2063
2295
  case expanded_receiver_type = expand_self(receiver_type)
2064
2296
  when AST::Types::Self
2065
- Steep.logger.error "`self` type cannot be resolved to concrete type"
2297
+ Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
2066
2298
  fallback_to_any node do
2067
2299
  Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
2068
2300
  end
@@ -2203,139 +2435,68 @@ module Steep
2203
2435
  def type_method_call(node, method_name:, receiver_type:, method:, args:, block_params:, block_body:, topdown_hint:)
2204
2436
  node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
2205
2437
 
2206
- case
2207
- when method.union?
2208
- yield_self do
2209
- results = method.types.map do |method|
2438
+ results = method.method_types.flat_map do |method_type|
2439
+ Steep.logger.tagged method_type.to_s do
2440
+ zips = args.zips(method_type.params, method_type.block&.type)
2441
+
2442
+ zips.map do |arg_pairs|
2210
2443
  typing.new_child(node_range) do |child_typing|
2211
- with_new_typing(child_typing).type_method_call(node,
2212
- method_name: method_name,
2213
- receiver_type: receiver_type,
2214
- method: method,
2215
- args: args,
2216
- block_params: block_params,
2217
- block_body: block_body,
2218
- topdown_hint: false)
2219
- end
2220
- end
2444
+ ret = self.with_new_typing(child_typing).try_method_type(
2445
+ node,
2446
+ receiver_type: receiver_type,
2447
+ method_type: method_type,
2448
+ args: args,
2449
+ arg_pairs: arg_pairs,
2450
+ block_params: block_params,
2451
+ block_body: block_body,
2452
+ child_typing: child_typing,
2453
+ topdown_hint: topdown_hint
2454
+ )
2221
2455
 
2222
- if (type, constr, error = results.find {|_, _, error| error })
2223
- constr.typing.save!
2224
- [type,
2225
- update_lvar_env { constr.context.lvar_env },
2226
- error]
2227
- else
2228
- types = results.map(&:first)
2456
+ raise unless ret.is_a?(Array) && ret[1].is_a?(TypeConstruction)
2229
2457
 
2230
- _, constr, _ = results.first
2231
- constr.typing.save!
2458
+ result, constr = ret
2232
2459
 
2233
- [union_type(*types),
2234
- update_lvar_env { constr.context.lvar_env },
2235
- nil]
2460
+ [result, constr, method_type]
2461
+ end
2236
2462
  end
2237
2463
  end
2464
+ end
2238
2465
 
2239
- when method.intersection?
2240
- yield_self do
2241
- results = method.types.map do |method|
2242
- typing.new_child(node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }) do |child_typing|
2243
- with_new_typing(child_typing).type_method_call(node,
2466
+ unless results.empty?
2467
+ result, constr, method_type = results.find {|result, _, _| !result.is_a?(Errors::Base) } || results.last
2468
+ else
2469
+ method_type = method.method_types.last
2470
+ constr = self.with_new_typing(typing.new_child(node_range))
2471
+ result = Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
2472
+ end
2473
+ constr.typing.save!
2474
+
2475
+ case result
2476
+ when Errors::Base
2477
+ if method.method_types.size == 1
2478
+ typing.add_error result
2479
+ type = case method_type.return_type
2480
+ when AST::Types::Var
2481
+ AST::Builtin.any_type
2482
+ else
2483
+ method_type.return_type
2484
+ end
2485
+ else
2486
+ typing.add_error Errors::UnresolvedOverloading.new(node: node,
2487
+ receiver_type: expand_self(receiver_type),
2244
2488
  method_name: method_name,
2245
- receiver_type: receiver_type,
2246
- method: method,
2247
- args: args,
2248
- block_params: block_params,
2249
- block_body: block_body,
2250
- topdown_hint: false)
2251
- end
2252
- end
2253
-
2254
- successes = results.reject {|_, _, error| error }
2255
- unless successes.empty?
2256
- types = successes.map(&:first)
2257
- constr = successes[0][1]
2258
- constr.typing.save!
2259
-
2260
- [AST::Types::Intersection.build(types: types),
2261
- update_lvar_env { constr.context.lvar_env },
2262
- nil]
2263
- else
2264
- type, constr, error = results.first
2265
- constr.typing.save!
2266
-
2267
- [type,
2268
- update_lvar_env { constr.context.lvar_env },
2269
- error]
2270
- end
2489
+ method_types: method.method_types)
2490
+ type = AST::Builtin.any_type
2271
2491
  end
2272
2492
 
2273
- when method.overload?
2274
- yield_self do
2275
- results = method.types.flat_map do |method_type|
2276
- Steep.logger.tagged method_type.to_s do
2277
- zips = args.zips(method_type.params, method_type.block&.type)
2278
-
2279
- zips.map do |arg_pairs|
2280
- typing.new_child(node_range) do |child_typing|
2281
- ret = self.with_new_typing(child_typing).try_method_type(
2282
- node,
2283
- receiver_type: receiver_type,
2284
- method_type: method_type,
2285
- args: args,
2286
- arg_pairs: arg_pairs,
2287
- block_params: block_params,
2288
- block_body: block_body,
2289
- child_typing: child_typing,
2290
- topdown_hint: topdown_hint
2291
- )
2292
-
2293
- raise unless ret.is_a?(Array) && ret[1].is_a?(TypeConstruction)
2294
-
2295
- result, constr = ret
2296
-
2297
- [result, constr, method_type]
2298
- end
2299
- end
2300
- end
2301
- end
2302
-
2303
- unless results.empty?
2304
- result, constr, method_type = results.find {|result, _, _| !result.is_a?(Errors::Base) } || results.last
2305
- else
2306
- method_type = method.types.last
2307
- constr = self.with_new_typing(typing.new_child(node_range))
2308
- result = Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
2309
- end
2310
- constr.typing.save!
2311
-
2312
- case result
2313
- when Errors::Base
2314
- if method.types.size == 1
2315
- typing.add_error result
2316
- type = case method_type.return_type
2317
- when AST::Types::Var
2318
- AST::Builtin.any_type
2319
- else
2320
- method_type.return_type
2321
- end
2322
- else
2323
- typing.add_error Errors::UnresolvedOverloading.new(node: node,
2324
- receiver_type: expand_self(receiver_type),
2325
- method_name: method_name,
2326
- method_types: method.types)
2327
- type = AST::Builtin.any_type
2328
- end
2329
-
2330
- [type,
2331
- update_lvar_env { constr.context.lvar_env },
2332
- result]
2333
- else # Type
2334
- [result,
2335
- update_lvar_env { constr.context.lvar_env },
2336
- nil]
2337
- end
2338
- end
2493
+ [type,
2494
+ update_lvar_env { constr.context.lvar_env },
2495
+ result]
2496
+ else # Type
2497
+ [result,
2498
+ update_lvar_env { constr.context.lvar_env },
2499
+ nil]
2339
2500
  end
2340
2501
  end
2341
2502
 
@@ -2522,16 +2683,40 @@ module Steep
2522
2683
  if block_params && method_type.block
2523
2684
  block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2524
2685
  block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
2525
- block_param_hint = block_params_.params_type(
2526
- hint: topdown_hint ? method_type.block.type.params : nil
2527
- )
2528
2686
 
2529
- check_relation(sub_type: AST::Types::Proc.new(params: block_param_hint, return_type: AST::Types::Any.new),
2530
- super_type: method_type.block.type,
2531
- constraints: constraints).else do |result|
2532
- return [Errors::IncompatibleBlockParameters.new(node: node,
2533
- method_type: method_type),
2534
- constr]
2687
+ unless block_params_
2688
+ return [
2689
+ Errors::UnsupportedSyntax.new(
2690
+ node: block_params,
2691
+ message: "Unsupported block params pattern, probably masgn?"
2692
+ ),
2693
+ constr
2694
+ ]
2695
+ end
2696
+
2697
+ pairs = block_params_.zip(method_type.block.type.params)
2698
+
2699
+ unless pairs
2700
+ return [
2701
+ Errors::IncompatibleBlockParameters.new(node: node, method_type: method_type),
2702
+ constr
2703
+ ]
2704
+ end
2705
+
2706
+ pairs.each do |param, type|
2707
+ if param.type
2708
+ check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
2709
+ return [
2710
+ Errors::IncompatibleAssignment.new(
2711
+ node: param.node,
2712
+ lhs_type: param.type,
2713
+ rhs_type: type,
2714
+ result: result
2715
+ ),
2716
+ constr
2717
+ ]
2718
+ end
2719
+ end
2535
2720
  end
2536
2721
  end
2537
2722
 
@@ -3005,7 +3190,12 @@ module Steep
3005
3190
 
3006
3191
  ty = case type
3007
3192
  when AST::Types::Name::Alias
3008
- deep_expand_alias(expand_alias(type), recursive: recursive << type)
3193
+ deep_expand_alias(expand_alias(type), recursive: recursive.union([type]))
3194
+ when AST::Types::Union
3195
+ AST::Types::Union.build(
3196
+ types: type.types.map {|ty| deep_expand_alias(ty, recursive: recursive, &block) },
3197
+ location: type.location
3198
+ )
3009
3199
  else
3010
3200
  type
3011
3201
  end
@@ -3017,19 +3207,51 @@ module Steep
3017
3207
  end
3018
3208
  end
3019
3209
 
3210
+ def flatten_union(type, acc = [])
3211
+ case type
3212
+ when AST::Types::Union
3213
+ type.types.each {|ty| flatten_union(ty, acc) }
3214
+ else
3215
+ acc << type
3216
+ end
3217
+
3218
+ acc
3219
+ end
3220
+
3221
+ def select_flatten_types(type, &block)
3222
+ types = flatten_union(deep_expand_alias(type))
3223
+ types.select(&block)
3224
+ end
3225
+
3226
+ def partition_flatten_types(type, &block)
3227
+ types = flatten_union(deep_expand_alias(type))
3228
+ types.partition(&block)
3229
+ end
3230
+
3231
+ def flatten_array_elements(type)
3232
+ flatten_union(deep_expand_alias(type)).flat_map do |type|
3233
+ if AST::Builtin::Array.instance_type?(type)
3234
+ type.args
3235
+ else
3236
+ [type]
3237
+ end
3238
+ end
3239
+ end
3240
+
3020
3241
  def expand_alias(type, &block)
3021
3242
  checker.factory.expand_alias(type, &block)
3022
3243
  end
3023
3244
 
3024
3245
  def test_literal_type(literal, hint)
3025
- case hint
3026
- when AST::Types::Literal
3027
- if hint.value == literal
3028
- hint
3029
- end
3030
- when AST::Types::Union
3031
- if hint.types.any? {|ty| ty.is_a?(AST::Types::Literal) && ty.value == literal}
3032
- hint
3246
+ if hint
3247
+ case hint
3248
+ when AST::Types::Any
3249
+ nil
3250
+ else
3251
+ literal_type = AST::Types::Literal.new(value: literal, location: nil)
3252
+ if check_relation(sub_type: literal_type, super_type: hint).success?
3253
+ hint
3254
+ end
3033
3255
  end
3034
3256
  end
3035
3257
  end
@@ -3054,7 +3276,7 @@ module Steep
3054
3276
 
3055
3277
  def to_instance_type(type, args: nil)
3056
3278
  args = args || case type
3057
- when AST::Types::Name::Class, AST::Types::Name::Module
3279
+ when AST::Types::Name::Singleton
3058
3280
  checker.factory.env.class_decls[checker.factory.type_name_1(type.name)].type_params.each.map { AST::Builtin.any_type }
3059
3281
  else
3060
3282
  raise "unexpected type to to_instance_type: #{type}"
@@ -3063,6 +3285,47 @@ module Steep
3063
3285
  AST::Types::Name::Instance.new(name: type.name, args: args)
3064
3286
  end
3065
3287
 
3288
+ def try_tuple_type(node, hint)
3289
+ if node.children.size != hint.types.size
3290
+ return
3291
+ end
3292
+
3293
+ constr = self
3294
+ element_types = []
3295
+
3296
+ each_child_node(node).with_index do |child, index|
3297
+ type, constr = constr.synthesize(child, hint: hint.types[index])
3298
+ element_types << type
3299
+ end
3300
+
3301
+ constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
3302
+ end
3303
+
3304
+ def try_array_type(node, hint)
3305
+ element_hint = hint ? hint.args[0] : nil
3306
+
3307
+ constr = self
3308
+ element_types = []
3309
+
3310
+ each_child_node(node) do |child|
3311
+ case child.type
3312
+ when :splat
3313
+ type, constr = constr.synthesize(child.children[0], hint: hint)
3314
+ if AST::Builtin::Array.instance_type?(type)
3315
+ element_types << type.args[0]
3316
+ else
3317
+ element_types.push(*flatten_array_elements(type))
3318
+ end
3319
+ else
3320
+ type, constr = constr.synthesize(child, hint: element_hint)
3321
+ element_types << type
3322
+ end
3323
+ end
3324
+
3325
+ element_type = AST::Types::Union.build(types: element_types)
3326
+ constr.add_typing(node, type: AST::Builtin::Array.instance_type(element_type))
3327
+ end
3328
+
3066
3329
  def try_hash_type(node, hint)
3067
3330
  case hint
3068
3331
  when AST::Types::Record