steep 0.1.0.pre

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 (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +4 -0
  5. data/README.md +95 -0
  6. data/Rakefile +23 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +8 -0
  9. data/bin/smoke_runner.rb +106 -0
  10. data/exe/steep +18 -0
  11. data/lib/steep.rb +33 -0
  12. data/lib/steep/annotation.rb +223 -0
  13. data/lib/steep/cli.rb +79 -0
  14. data/lib/steep/drivers/check.rb +141 -0
  15. data/lib/steep/errors.rb +207 -0
  16. data/lib/steep/interface.rb +280 -0
  17. data/lib/steep/parser.y +311 -0
  18. data/lib/steep/signature/class.rb +358 -0
  19. data/lib/steep/signature/errors.rb +78 -0
  20. data/lib/steep/signature/extension.rb +51 -0
  21. data/lib/steep/signature/interface.rb +48 -0
  22. data/lib/steep/source.rb +98 -0
  23. data/lib/steep/type_assignability.rb +362 -0
  24. data/lib/steep/type_construction.rb +993 -0
  25. data/lib/steep/type_name.rb +37 -0
  26. data/lib/steep/types.rb +4 -0
  27. data/lib/steep/types/any.rb +31 -0
  28. data/lib/steep/types/class.rb +27 -0
  29. data/lib/steep/types/instance.rb +27 -0
  30. data/lib/steep/types/merge.rb +32 -0
  31. data/lib/steep/types/name.rb +57 -0
  32. data/lib/steep/types/union.rb +42 -0
  33. data/lib/steep/types/var.rb +38 -0
  34. data/lib/steep/typing.rb +70 -0
  35. data/lib/steep/version.rb +3 -0
  36. data/manual/annotations.md +144 -0
  37. data/sig/signature.rbi +54 -0
  38. data/sig/types.rbi +43 -0
  39. data/smoke/and/a.rb +9 -0
  40. data/smoke/array/a.rb +22 -0
  41. data/smoke/block/a.rb +12 -0
  42. data/smoke/block/a.rbi +4 -0
  43. data/smoke/case/a.rb +20 -0
  44. data/smoke/class/a.rb +31 -0
  45. data/smoke/class/a.rbi +9 -0
  46. data/smoke/class/b.rb +7 -0
  47. data/smoke/class/c.rb +10 -0
  48. data/smoke/const/a.rb +30 -0
  49. data/smoke/dstr/a.rb +6 -0
  50. data/smoke/extension/a.rb +11 -0
  51. data/smoke/extension/a.rbi +8 -0
  52. data/smoke/extension/b.rb +12 -0
  53. data/smoke/extension/c.rb +9 -0
  54. data/smoke/hello/hello.rb +13 -0
  55. data/smoke/hello/hello.rbi +7 -0
  56. data/smoke/if/a.rb +20 -0
  57. data/smoke/implements/a.rb +14 -0
  58. data/smoke/implements/a.rbi +6 -0
  59. data/smoke/literal/a.rb +16 -0
  60. data/smoke/map/a.rb +5 -0
  61. data/smoke/method/a.rb +26 -0
  62. data/smoke/method/a.rbi +0 -0
  63. data/smoke/module/a.rb +21 -0
  64. data/smoke/module/a.rbi +7 -0
  65. data/smoke/module/b.rb +8 -0
  66. data/smoke/self/a.rb +23 -0
  67. data/smoke/self/a.rbi +4 -0
  68. data/smoke/super/a.rb +34 -0
  69. data/smoke/super/a.rbi +10 -0
  70. data/smoke/yield/a.rb +18 -0
  71. data/stdlib/builtin.rbi +89 -0
  72. data/steep.gemspec +32 -0
  73. metadata +214 -0
@@ -0,0 +1,993 @@
1
+ module Steep
2
+ class TypeConstruction
3
+ class MethodContext
4
+ attr_reader :name
5
+ attr_reader :method
6
+
7
+ def initialize(name:, method:, method_type:, return_type:)
8
+ @name = name
9
+ @method = method
10
+ @return_type = return_type
11
+ @method_type = method_type
12
+ end
13
+
14
+ def return_type
15
+ @return_type || method_type&.return_type
16
+ end
17
+
18
+ def block_type
19
+ method_type&.block
20
+ end
21
+
22
+ def method_type
23
+ @method_type || method&.types&.first
24
+ end
25
+
26
+ def super_type
27
+ method&.super_method&.types&.first
28
+ end
29
+ end
30
+
31
+ class BlockContext
32
+ attr_reader :break_type
33
+ attr_reader :body_type
34
+
35
+ def initialize(break_type:, body_type:)
36
+ @break_type = break_type
37
+ @body_type = body_type
38
+ end
39
+ end
40
+
41
+ class ModuleContext
42
+ attr_reader :instance_type
43
+ attr_reader :module_type
44
+ attr_reader :defined_instance_methods
45
+ attr_reader :defined_module_methods
46
+ attr_reader :const_types
47
+
48
+ def initialize(instance_type:, module_type:, const_types:)
49
+ @instance_type = instance_type
50
+ @module_type = module_type
51
+ @defined_instance_methods = Set.new
52
+ @defined_module_methods = Set.new
53
+ @const_types = const_types
54
+ end
55
+ end
56
+
57
+ attr_reader :assignability
58
+ attr_reader :source
59
+ attr_reader :annotations
60
+ attr_reader :var_types
61
+ attr_reader :ivar_types
62
+ attr_reader :typing
63
+ attr_reader :method_context
64
+ attr_reader :block_context
65
+ attr_reader :module_context
66
+ attr_reader :self_type
67
+
68
+ def initialize(assignability:, source:, annotations:, var_types:, ivar_types: {}, typing:, self_type:, method_context:, block_context:, module_context:)
69
+ @assignability = assignability
70
+ @source = source
71
+ @annotations = annotations
72
+ @var_types = var_types
73
+ @ivar_types = ivar_types
74
+ @typing = typing
75
+ @self_type = self_type
76
+ @block_context = block_context
77
+ @method_context = method_context
78
+ @module_context = module_context
79
+ end
80
+
81
+ def method_entry(method_name, receiver_type:)
82
+ if receiver_type
83
+ entry = nil
84
+ assignability.method_type receiver_type, method_name do |method|
85
+ entry = method
86
+ end
87
+ end
88
+
89
+ if (type = annotations.lookup_method_type(method_name))
90
+ Interface::Method.new(types: [type], super_method: entry&.super_method)
91
+ else
92
+ entry
93
+ end
94
+ end
95
+
96
+ def for_new_method(method_name, node, args:, self_type:)
97
+ annots = source.annotations(block: node)
98
+
99
+ self_type = annots.self_type || self_type
100
+
101
+ entry = method_entry(method_name, receiver_type: self_type)
102
+ method_type = entry&.types&.first
103
+ if method_type
104
+ var_types = TypeConstruction.parameter_types(args,
105
+ method_type)
106
+ unless TypeConstruction.valid_parameter_env?(var_types, args, method_type.params)
107
+ typing.add_error Errors::MethodParameterTypeMismatch.new(node: node)
108
+ end
109
+ else
110
+ var_types = {}
111
+ end
112
+
113
+ method_context = MethodContext.new(
114
+ name: method_name,
115
+ method: entry,
116
+ method_type: annotations.lookup_method_type(method_name),
117
+ return_type: annots.return_type,
118
+ )
119
+
120
+ ivar_types = annots.ivar_types.keys.each.with_object({}) do |var, env|
121
+ env[var] = annots.ivar_types[var]
122
+ end
123
+
124
+ self.class.new(
125
+ assignability: assignability,
126
+ source: source,
127
+ annotations: annots,
128
+ var_types: var_types,
129
+ block_context: nil,
130
+ self_type: self_type,
131
+ method_context: method_context,
132
+ typing: typing,
133
+ module_context: module_context,
134
+ ivar_types: ivar_types
135
+ )
136
+ end
137
+
138
+ def for_class(node)
139
+ annots = source.annotations(block: node)
140
+
141
+ if annots.implement_module
142
+ signature = assignability.signatures[annots.implement_module]
143
+ raise "Class implements should be an class: #{annots.instance_type}" unless signature.is_a?(Signature::Class)
144
+
145
+ instance_type = Types::Name.instance(name: annots.implement_module)
146
+ module_type = Types::Name.module(name: annots.implement_module)
147
+ end
148
+
149
+ module_context = ModuleContext.new(
150
+ instance_type: annots.instance_type || instance_type,
151
+ module_type: annots.module_type || module_type,
152
+ const_types: annots.const_types
153
+ )
154
+
155
+ self.class.new(
156
+ assignability: assignability,
157
+ source: source,
158
+ annotations: annots,
159
+ var_types: {},
160
+ typing: typing,
161
+ method_context: nil,
162
+ block_context: nil,
163
+ module_context: module_context,
164
+ self_type: module_context.module_type
165
+ )
166
+ end
167
+
168
+ def synthesize(node)
169
+ case node.type
170
+ when :begin
171
+ type = each_child_node(node).map do |child|
172
+ synthesize(child)
173
+ end.last
174
+
175
+ typing.add_typing(node, type)
176
+
177
+ when :lvasgn
178
+ var = node.children[0]
179
+ rhs = node.children[1]
180
+
181
+ type_assignment(var, rhs, node)
182
+
183
+ when :lvar
184
+ var = node.children[0]
185
+
186
+ if (type = variable_type(var))
187
+ typing.add_typing(node, type)
188
+ else
189
+ fallback_to_any node
190
+ typing.add_var_type var, Types::Any.new
191
+ end
192
+
193
+ when :ivasgn
194
+ name = node.children[0]
195
+ value = node.children[1]
196
+
197
+ if (type = ivar_types[name])
198
+ check(value, type) do |_, value_type|
199
+ typing.add_error(Errors::IncompatibleAssignment.new(node: node, lhs_type: type, rhs_type: value_type))
200
+ end
201
+ typing.add_typing(node, type)
202
+ else
203
+ value_type = synthesize(value)
204
+ typing.add_typing(node, value_type)
205
+ end
206
+
207
+ when :ivar
208
+ type = ivar_types[node.children[0]]
209
+ if type
210
+ typing.add_typing(node, type)
211
+ else
212
+ fallback_to_any node
213
+ end
214
+
215
+ when :send
216
+ type_send(node, with_block: false)
217
+
218
+ when :super
219
+ if self_type && method_context&.method
220
+ if method_context.super_type
221
+ ret_type = type_method_call(node: node,
222
+ receiver_type: self_type,
223
+ method_name: method_context.name,
224
+ arguments: node.children,
225
+ method_types: [method_context.super_type],
226
+ with_block: false)
227
+ else
228
+ typing.add_error(Errors::UnexpectedSuper.new(node: node, method: method_context.name))
229
+ end
230
+ end
231
+
232
+ if ret_type
233
+ typing.add_typing node, ret_type
234
+ else
235
+ fallback_to_any node
236
+ end
237
+
238
+ when :block
239
+ send_node, params, block = node.children
240
+
241
+ ret_type = type_send(send_node, with_block: true) do |recv_type, method_name, method_type|
242
+ if method_type.block
243
+ var_types_ = var_types.dup
244
+ self.class.block_param_typing_pairs(param_types: method_type.block.params, param_nodes: params.children).each do |param_node, type|
245
+ var = param_node.children[0]
246
+ var_types_[var] = type
247
+ typing.add_var_type(var, type)
248
+ end
249
+
250
+ annots = source.annotations(block: node)
251
+
252
+ block_context = BlockContext.new(body_type: annots.block_type,
253
+ break_type: method_type.return_type)
254
+
255
+ for_block = self.class.new(
256
+ assignability: assignability,
257
+ source: source,
258
+ annotations: annotations + annots,
259
+ var_types: var_types_,
260
+ block_context: block_context,
261
+ typing: typing,
262
+ method_context: method_context,
263
+ module_context: self.module_context,
264
+ self_type: annots.self_type || self_type
265
+ )
266
+
267
+ each_child_node(params) do |param|
268
+ for_block.synthesize(param)
269
+ end
270
+
271
+ case method_type.block.return_type
272
+ when Types::Var
273
+ block_type = block ? for_block.synthesize(block) : Types::Any.new
274
+ method_type_ = method_type.instantiate(subst: { method_type.block.return_type.name => block_type })
275
+ method_type_.return_type
276
+ else
277
+ if block
278
+ for_block.check(block, method_type.block.return_type) do |expected, actual|
279
+ typing.add_error Errors::BlockTypeMismatch.new(node: node, expected: expected, actual: actual)
280
+ end
281
+ end
282
+
283
+ method_type.return_type
284
+ end
285
+
286
+ else
287
+ typing.add_error Errors::UnexpectedBlockGiven.new(node: node, type: recv_type, method: method_name)
288
+ nil
289
+ end
290
+ end
291
+
292
+ typing.add_typing(node, ret_type)
293
+
294
+ when :def
295
+ new = for_new_method(node.children[0],
296
+ node,
297
+ args: node.children[1].children,
298
+ self_type: module_context&.instance_type)
299
+
300
+ each_child_node(node.children[1]) do |arg|
301
+ new.synthesize(arg)
302
+ end
303
+
304
+ if node.children[2]
305
+ return_type = new.method_context&.return_type
306
+ if return_type
307
+ new.check(node.children[2], return_type) do |_, actual_type|
308
+ typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
309
+ expected: return_type,
310
+ actual: actual_type))
311
+ end
312
+ else
313
+ new.synthesize(node.children[2])
314
+ end
315
+ end
316
+
317
+ if module_context
318
+ module_context.defined_instance_methods << node.children[0]
319
+ end
320
+
321
+ typing.add_typing(node, Types::Any.new)
322
+
323
+ when :defs
324
+ synthesize(node.children[0]).tap do |self_type|
325
+ new = for_new_method(node.children[1],
326
+ node,
327
+ args: node.children[2].children,
328
+ self_type: self_type)
329
+
330
+ each_child_node(node.children[2]) do |arg|
331
+ new.synthesize(arg)
332
+ end
333
+
334
+ if node.children[3]
335
+ if new&.method_context&.method_type
336
+ new.check(node.children[3], new.method_context.method_type.return_type) do |return_type, actual_type|
337
+ typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
338
+ expected: return_type,
339
+ actual: actual_type))
340
+ end
341
+ else
342
+ new.synthesize(node.children[3])
343
+ end
344
+ end
345
+ end
346
+
347
+ if module_context
348
+ if node.children[0].type == :self
349
+ module_context.defined_module_methods << node.children[1]
350
+ end
351
+ end
352
+
353
+ typing.add_typing(node, Types::Name.instance(name: :Symbol))
354
+
355
+ when :return
356
+ value = node.children[0]
357
+
358
+ if value
359
+ if method_context&.return_type
360
+ check(value, method_context.return_type) do |_, actual_type|
361
+ typing.add_error(Errors::ReturnTypeMismatch.new(node: node,
362
+ expected: method_context.return_type,
363
+ actual: actual_type))
364
+ end
365
+ else
366
+ synthesize(value)
367
+ end
368
+ end
369
+
370
+ typing.add_typing(node, Types::Any.new)
371
+
372
+ when :break
373
+ value = node.children[0]
374
+
375
+ if value
376
+ if block_context&.break_type
377
+ check(value, block_context.break_type) do |break_type, actual_type|
378
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
379
+ expected: break_type,
380
+ actual: actual_type)
381
+ end
382
+ else
383
+ synthesize(value)
384
+ end
385
+ end
386
+
387
+ typing.add_typing(node, Types::Any.new)
388
+
389
+ when :arg, :kwarg, :procarg0
390
+ var = node.children[0]
391
+ if (type = variable_type(var))
392
+ typing.add_var_type(var, type)
393
+ else
394
+ fallback_to_any node
395
+ end
396
+
397
+ when :optarg, :kwoptarg
398
+ var = node.children[0]
399
+ rhs = node.children[1]
400
+ type_assignment(var, rhs, node)
401
+
402
+ when :int
403
+ typing.add_typing(node, Types::Name.instance(name: :Integer))
404
+
405
+ when :nil
406
+ typing.add_typing(node, Types::Any.new)
407
+
408
+ when :sym
409
+ typing.add_typing(node, Types::Name.instance(name: :Symbol))
410
+
411
+ when :str
412
+ typing.add_typing(node, Types::Name.instance(name: :String))
413
+
414
+ when :true, :false
415
+ typing.add_typing(node, Types::Name.interface(name: :_Boolean))
416
+
417
+ when :hash
418
+ each_child_node(node) do |pair|
419
+ raise "Unexpected non pair: #{pair.inspect}" unless pair.type == :pair
420
+ each_child_node(pair) do |e|
421
+ synthesize(e)
422
+ end
423
+ end
424
+
425
+ typing.add_typing(node, Types::Any.new)
426
+
427
+ when :dstr
428
+ each_child_node(node) do |child|
429
+ synthesize(child)
430
+ end
431
+
432
+ typing.add_typing(node, Types::Name.instance(name: :String))
433
+
434
+ when :dsym
435
+ each_child_node(node) do |child|
436
+ synthesize(child)
437
+ end
438
+
439
+ typing.add_typing(node, Types::Name.instance(name: :Symbol))
440
+
441
+ when :class
442
+ for_class(node).tap do |constructor|
443
+ constructor.synthesize(node.children[2])
444
+ constructor.validate_method_definitions(node)
445
+ end
446
+
447
+ typing.add_typing(node, Types::Name.instance(name: :NilClass))
448
+
449
+ when :module
450
+ annots = source.annotations(block: node)
451
+
452
+ if annots.implement_module
453
+ signature = assignability.signatures[annots.implement_module]
454
+ raise "Module instance should be an module: #{annots.instance_type || annots.implment_module}" unless signature.is_a?(Signature::Module)
455
+
456
+ ty = Types::Name.instance(name: annots.implement_module)
457
+
458
+ if signature.self_type
459
+ instance_type = Types::Merge.new(types: [signature.self_type, ty])
460
+ else
461
+ instance_type = ty
462
+ end
463
+ end
464
+
465
+ if annots.instance_type
466
+ instance_type = annots.instance_type
467
+ end
468
+
469
+ module_context_ = ModuleContext.new(
470
+ instance_type: instance_type,
471
+ module_type: annots.module_type,
472
+ const_types: annots.const_types
473
+ )
474
+
475
+ for_class = self.class.new(
476
+ assignability: assignability,
477
+ source: source,
478
+ annotations: annots,
479
+ var_types: {},
480
+ typing: typing,
481
+ method_context: nil,
482
+ block_context: nil,
483
+ module_context: module_context_,
484
+ self_type: module_context_.module_type
485
+ )
486
+
487
+ for_class.synthesize(node.children[1]) if node.children[1]
488
+ for_class.validate_method_definitions(node)
489
+
490
+ typing.add_typing(node, Types::Name.instance(name: :NilClass))
491
+
492
+ when :self
493
+ if self_type
494
+ typing.add_typing(node, self_type)
495
+ else
496
+ fallback_to_any node
497
+ end
498
+
499
+ when :const
500
+ const_name = flatten_const_name(node)
501
+ if const_name
502
+ type = (module_context&.const_types || {})[const_name]
503
+ end
504
+
505
+ if type
506
+ typing.add_typing(node, type)
507
+ else
508
+ fallback_to_any node
509
+ end
510
+
511
+ when :yield
512
+ if method_context&.method_type
513
+ if method_context.block_type
514
+ block_type = method_context.block_type
515
+ block_type.params.flat_unnamed_params.map(&:last).zip(node.children).each do |(type, node)|
516
+ if node && type
517
+ check(node, type) do |_, rhs_type|
518
+ typing.add_error(Errors::IncompatibleAssignment.new(node: node, lhs_type: type, rhs_type: rhs_type))
519
+ end
520
+ end
521
+ end
522
+
523
+ typing.add_typing(node, block_type.return_type)
524
+ else
525
+ typing.add_error(Errors::UnexpectedYield.new(node: node))
526
+ fallback_to_any node
527
+ end
528
+ else
529
+ fallback_to_any node
530
+ end
531
+
532
+ when :zsuper
533
+ if method_context&.method
534
+ if method_context.super_type
535
+ typing.add_typing(node, method_context.super_type.return_type)
536
+ else
537
+ typing.add_error(Errors::UnexpectedSuper.new(node: node, method: method_context.name))
538
+ fallback_to_any node
539
+ end
540
+ else
541
+ fallback_to_any node
542
+ end
543
+
544
+ when :array
545
+ if node.children.empty?
546
+ typing.add_typing(node, Types::Name.instance(name: :Array, params: [Types::Any.new]))
547
+ else
548
+ types = node.children.map {|e| synthesize(e) }
549
+
550
+ if types.uniq.size == 1
551
+ typing.add_typing(node, Types::Name.instance(name: :Array, params: [types.first]))
552
+ else
553
+ typing.add_typing(node, Types::Name.instance(name: :Array, params: [Types::Any.new]))
554
+ end
555
+ end
556
+
557
+ when :and
558
+ types = each_child_node(node).map {|child| synthesize(child) }
559
+ typing.add_typing(node, types.last)
560
+
561
+ when :or
562
+ types = each_child_node(node).map {|child| synthesize(child) }
563
+ type = union_type(*types)
564
+ typing.add_typing(node, type)
565
+
566
+ when :if
567
+ cond, true_clause, false_clause = node.children
568
+ synthesize cond
569
+ true_type = synthesize(true_clause) if true_clause
570
+ false_type = synthesize(false_clause) if false_clause
571
+
572
+ typing.add_typing(node, union_type(true_type, false_type))
573
+
574
+ when :case
575
+ cond, *whens = node.children
576
+
577
+ synthesize cond if cond
578
+
579
+ types = whens.map do |clause|
580
+ if clause&.type == :when
581
+ clause.children.take(clause.children.size - 1).map do |child|
582
+ synthesize(child)
583
+ end
584
+
585
+ if (body = clause.children.last)
586
+ synthesize body
587
+ else
588
+ fallback_to_any body
589
+ end
590
+ else
591
+ synthesize clause if clause
592
+ end
593
+ end
594
+
595
+ typing.add_typing(node, union_type(*types))
596
+
597
+ else
598
+ raise "Unexpected node: #{node.inspect}, #{node.location.line}"
599
+ end
600
+ end
601
+
602
+ def check(node, type)
603
+ type_ = synthesize(node)
604
+
605
+ unless assignability.test(src: type_, dest: type)
606
+ yield(type, type_)
607
+ end
608
+ end
609
+
610
+ def type_assignment(var, rhs, node)
611
+ lhs_type = variable_type(var)
612
+
613
+ if rhs
614
+ if lhs_type
615
+ check(rhs, lhs_type) do |_, rhs_type|
616
+ typing.add_error(Errors::IncompatibleAssignment.new(node: node, lhs_type: lhs_type, rhs_type: rhs_type))
617
+ end
618
+ typing.add_var_type(var, lhs_type)
619
+ typing.add_typing(node, lhs_type)
620
+ var_types[var] = lhs_type
621
+ lhs_type
622
+ else
623
+ rhs_type = synthesize(rhs)
624
+ typing.add_var_type(var, rhs_type)
625
+ typing.add_typing(node, rhs_type)
626
+ var_types[var] = rhs_type
627
+ rhs_type
628
+ end
629
+ else
630
+ if lhs_type
631
+ typing.add_var_type(var, lhs_type)
632
+ typing.add_typing(node, lhs_type)
633
+ var_types[var] = lhs_type
634
+ else
635
+ typing.add_var_type(var, Types::Any.new)
636
+ fallback_to_any node
637
+ var_types[var] = Types::Any.new
638
+ end
639
+ end
640
+ end
641
+
642
+ def type_method_call(node:, receiver_type:, method_name:, method_types:, arguments:, with_block: false)
643
+ method_type = method_types.flat_map do |type|
644
+ next unless with_block == !!type.block
645
+
646
+ var_types_mapping = {}
647
+
648
+ type.type_params.each do |param|
649
+ var_types_mapping[param] = []
650
+ end
651
+
652
+ catch :abort do
653
+ pairs = test_args(params: type.params, arguments: arguments)
654
+ if pairs
655
+ arg_types = pairs.map {|(_, arg_node)| synthesize(arg_node) }
656
+
657
+ pairs.each.with_index do |(param_type, _), index|
658
+ arg_type = arg_types[index]
659
+
660
+ case param_type
661
+ when Types::Var
662
+ var_types_mapping[param_type.name] << arg_type
663
+ else
664
+ unless assignability.test(src: arg_type, dest: param_type)
665
+ throw :abort
666
+ end
667
+ end
668
+ end
669
+
670
+ subst = var_types_mapping.each.with_object({}) do |(name, types), subst|
671
+ unless types.empty?
672
+ compacted_types = assignability.compact(types)
673
+
674
+ if compacted_types.size > 1
675
+ subst[name] = Types::Union.new(types: compacted_types)
676
+ else
677
+ subst[name] = compacted_types.first
678
+ end
679
+ end
680
+ end
681
+
682
+ type.instantiate(subst: subst)
683
+ end
684
+ end
685
+ end.compact.first
686
+
687
+ if method_type
688
+ if block_given?
689
+ return_type = yield(receiver_type, method_name, method_type)
690
+ end
691
+ return_type || method_type.return_type
692
+ else
693
+ arguments.each do |arg|
694
+ synthesize(arg)
695
+ end
696
+
697
+ typing.add_error Errors::ArgumentTypeMismatch.new(node: node, type: receiver_type, method: method_name)
698
+ nil
699
+ end
700
+ end
701
+
702
+ def type_send(node, with_block:, &block)
703
+ receiver, method_name, *args = node.children
704
+ receiver_type = receiver ? synthesize(receiver) : self_type
705
+
706
+ if receiver_type
707
+ ret_type = assignability.method_type receiver_type, method_name do |method|
708
+ if method
709
+ type_method_call(node: node,
710
+ receiver_type: receiver_type,
711
+ method_name: method_name,
712
+ arguments: args,
713
+ method_types: method.types,
714
+ with_block: with_block,
715
+ &block)
716
+ else
717
+ args.each {|arg| synthesize(arg) }
718
+ typing.add_error Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
719
+ nil
720
+ end
721
+ end
722
+
723
+ typing.add_typing node, ret_type
724
+ else
725
+ fallback_to_any node
726
+ end
727
+ end
728
+
729
+ def variable_type(var)
730
+ var_types[var] || annotations.lookup_var_type(var.name)
731
+ end
732
+
733
+ def each_child_node(node)
734
+ if block_given?
735
+ node.children.each do |child|
736
+ if child.is_a?(AST::Node)
737
+ yield child
738
+ end
739
+ end
740
+ else
741
+ enum_for :each_child_node, node
742
+ end
743
+ end
744
+
745
+ def test_args(params:, arguments:)
746
+ params.each_missing_argument arguments do |_|
747
+ return nil
748
+ end
749
+
750
+ params.each_extra_argument arguments do |_|
751
+ return nil
752
+ end
753
+
754
+ params.each_missing_keyword arguments do |_|
755
+ return nil
756
+ end
757
+
758
+ params.each_extra_keyword arguments do |_|
759
+ return nil
760
+ end
761
+
762
+ self.class.argument_typing_pairs(params: params, arguments: arguments.dup)
763
+ end
764
+
765
+ def applicable_args?(params:, arguments:)
766
+ params.each_missing_argument arguments do |_|
767
+ return false
768
+ end
769
+
770
+ params.each_extra_argument arguments do |_|
771
+ return false
772
+ end
773
+
774
+ params.each_missing_keyword arguments do |_|
775
+ return false
776
+ end
777
+
778
+ params.each_extra_keyword arguments do |_|
779
+ return false
780
+ end
781
+
782
+ all_args = arguments.dup
783
+
784
+ self.class.argument_typing_pairs(params: params, arguments: arguments.dup).each do |(param_type, argument)|
785
+ all_args.delete_if {|a| a.equal?(argument) }
786
+
787
+ check(argument, param_type) do |_, _|
788
+ return false
789
+ end
790
+ end
791
+
792
+ all_args.each do |arg|
793
+ synthesize(arg)
794
+ end
795
+
796
+ true
797
+ end
798
+
799
+ def self.block_param_typing_pairs(param_types: , param_nodes:)
800
+ pairs = []
801
+
802
+ param_types.required.each.with_index do |type, index|
803
+ if (param = param_nodes[index])
804
+ pairs << [param, type]
805
+ end
806
+ end
807
+
808
+ pairs
809
+ end
810
+
811
+ def self.argument_typing_pairs(params:, arguments:)
812
+ keywords = {}
813
+ unless params.required_keywords.empty? && params.optional_keywords.empty? && !params.rest_keywords
814
+ # has keyword args
815
+ last_arg = arguments.last
816
+ if last_arg&.type == :hash
817
+ arguments.pop
818
+
819
+ last_arg.children.each do |elem|
820
+ case elem.type
821
+ when :pair
822
+ key, value = elem.children
823
+ if key.type == :sym
824
+ name = key.children[0]
825
+
826
+ keywords[name] = value
827
+ end
828
+ end
829
+ end
830
+ end
831
+ end
832
+
833
+ pairs = []
834
+
835
+ params.flat_unnamed_params.each do |param_type|
836
+ arg = arguments.shift
837
+ pairs << [param_type.last, arg] if arg
838
+ end
839
+
840
+ if params.rest
841
+ arguments.each do |arg|
842
+ pairs << [params.rest, arg]
843
+ end
844
+ end
845
+
846
+ params.flat_keywords.each do |name, type|
847
+ arg = keywords.delete(name)
848
+ if arg
849
+ pairs << [type, arg]
850
+ end
851
+ end
852
+
853
+ if params.rest_keywords
854
+ keywords.each_value do |arg|
855
+ pairs << [params.rest_keywords, arg]
856
+ end
857
+ end
858
+
859
+ pairs
860
+ end
861
+
862
+ def self.parameter_types(nodes, type)
863
+ nodes = nodes.dup
864
+
865
+ env = {}
866
+
867
+ type.params.required.each do |type|
868
+ a = nodes.first
869
+ if a&.type == :arg
870
+ env[a.children.first] = type
871
+ nodes.shift
872
+ else
873
+ break
874
+ end
875
+ end
876
+
877
+ type.params.optional.each do |type|
878
+ a = nodes.first
879
+
880
+ if a&.type == :optarg
881
+ env[a.children.first] = type
882
+ nodes.shift
883
+ else
884
+ break
885
+ end
886
+ end
887
+
888
+ if type.params.rest
889
+ a = nodes.first
890
+ if a&.type == :restarg
891
+ env[a.children.first] = Types::Name.instance(name: :Array, params: [type.params.rest])
892
+ nodes.shift
893
+ end
894
+ end
895
+
896
+ nodes.each do |node|
897
+ if node.type == :kwarg
898
+ name = node.children[0]
899
+ ty = type.params.required_keywords[name.name]
900
+ env[name] = ty if ty
901
+ end
902
+
903
+ if node.type == :kwoptarg
904
+ name = node.children[0]
905
+ ty = type.params.optional_keywords[name.name]
906
+ env[name] = ty if ty
907
+ end
908
+
909
+ if node.type == :kwrestarg
910
+ ty = type.params.rest_keywords
911
+ if ty
912
+ env[node.children[0]] = Types::Name.instance(name: :Hash,
913
+ params: [Types::Name.instance(name: :Symbol), ty])
914
+ end
915
+ end
916
+ end
917
+
918
+ env
919
+ end
920
+
921
+ def self.valid_parameter_env?(env, nodes, params)
922
+ env.size == nodes.size && env.size == params.size
923
+ end
924
+
925
+ def union_type(*types)
926
+ types_ = assignability.compact(types.compact)
927
+
928
+ if types_.size == 1
929
+ types_.first
930
+ else
931
+ Types::Union.new(types: types_)
932
+ end
933
+ end
934
+
935
+ def validate_method_definitions(node)
936
+ implements = annotations.implement_module
937
+ if implements
938
+ signature = assignability.signatures[implements]
939
+ signature.members.each do |member|
940
+ if member.is_a?(Signature::Members::InstanceMethod) || member.is_a?(Signature::Members::ModuleInstanceMethod)
941
+ unless module_context.defined_instance_methods.include?(member.name) || annotations.dynamics.member?(member.name)
942
+ typing.add_error Errors::MethodDefinitionMissing.new(node: node,
943
+ module_name: implements,
944
+ kind: :instance,
945
+ missing_method: member.name)
946
+ end
947
+
948
+ end
949
+ if member.is_a?(Signature::Members::ModuleMethod) || member.is_a?(Signature::Members::ModuleInstanceMethod)
950
+ unless module_context.defined_module_methods.include?(member.name)
951
+ typing.add_error Errors::MethodDefinitionMissing.new(node: node,
952
+ module_name: implements,
953
+ kind: :module,
954
+ missing_method: member.name)
955
+ end
956
+ end
957
+ end
958
+
959
+ annotations.dynamics.each do |method_name|
960
+ unless signature.members.any? {|sig| sig.is_a?(Signature::Members::InstanceMethod) && sig.name == method_name }
961
+ typing.add_error Errors::UnexpectedDynamicMethod.new(node: node,
962
+ module_name: implements,
963
+ method_name: method_name)
964
+ end
965
+ end
966
+ end
967
+ end
968
+
969
+ def flatten_const_name(node)
970
+ path = []
971
+
972
+ while node
973
+ case node.type
974
+ when :const
975
+ path.unshift(node.children[1])
976
+ node = node.children[0]
977
+ when :cbase
978
+ path.unshift("")
979
+ break
980
+ else
981
+ return nil
982
+ end
983
+ end
984
+
985
+ path.join("::").to_sym
986
+ end
987
+
988
+ def fallback_to_any(node)
989
+ typing.add_error Errors::FallbackAny.new(node: node)
990
+ typing.add_typing node, Types::Any.new
991
+ end
992
+ end
993
+ end