steep 0.22.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
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