steep 0.22.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -1
  3. data/bin/smoke_runner.rb +3 -4
  4. data/lib/steep.rb +1 -1
  5. data/lib/steep/ast/builtin.rb +2 -20
  6. data/lib/steep/ast/types.rb +5 -3
  7. data/lib/steep/ast/types/any.rb +1 -3
  8. data/lib/steep/ast/types/boolean.rb +1 -3
  9. data/lib/steep/ast/types/bot.rb +1 -3
  10. data/lib/steep/ast/types/class.rb +2 -2
  11. data/lib/steep/ast/types/factory.rb +106 -55
  12. data/lib/steep/ast/types/helper.rb +6 -0
  13. data/lib/steep/ast/types/instance.rb +2 -2
  14. data/lib/steep/ast/types/intersection.rb +20 -13
  15. data/lib/steep/ast/types/literal.rb +1 -3
  16. data/lib/steep/ast/types/name.rb +15 -67
  17. data/lib/steep/ast/types/nil.rb +1 -3
  18. data/lib/steep/ast/types/proc.rb +5 -2
  19. data/lib/steep/ast/types/record.rb +9 -4
  20. data/lib/steep/ast/types/self.rb +1 -1
  21. data/lib/steep/ast/types/top.rb +1 -3
  22. data/lib/steep/ast/types/tuple.rb +5 -3
  23. data/lib/steep/ast/types/union.rb +16 -9
  24. data/lib/steep/ast/types/var.rb +2 -2
  25. data/lib/steep/ast/types/void.rb +1 -3
  26. data/lib/steep/drivers/check.rb +4 -0
  27. data/lib/steep/errors.rb +14 -0
  28. data/lib/steep/interface/interface.rb +5 -62
  29. data/lib/steep/interface/method_type.rb +383 -92
  30. data/lib/steep/interface/substitution.rb +48 -6
  31. data/lib/steep/project/completion_provider.rb +1 -1
  32. data/lib/steep/project/hover_content.rb +1 -1
  33. data/lib/steep/project/target.rb +5 -2
  34. data/lib/steep/server/base_worker.rb +5 -3
  35. data/lib/steep/server/code_worker.rb +2 -0
  36. data/lib/steep/server/master.rb +10 -1
  37. data/lib/steep/source.rb +4 -3
  38. data/lib/steep/subtyping/check.rb +49 -60
  39. data/lib/steep/type_construction.rb +629 -366
  40. data/lib/steep/type_inference/block_params.rb +5 -0
  41. data/lib/steep/type_inference/constant_env.rb +1 -1
  42. data/lib/steep/type_inference/context.rb +8 -0
  43. data/lib/steep/type_inference/context_array.rb +4 -3
  44. data/lib/steep/type_inference/logic.rb +31 -0
  45. data/lib/steep/typing.rb +7 -0
  46. data/lib/steep/version.rb +1 -1
  47. data/smoke/alias/a.rb +1 -1
  48. data/smoke/case/a.rb +1 -1
  49. data/smoke/hash/d.rb +1 -1
  50. data/smoke/if/a.rb +1 -1
  51. data/smoke/module/a.rb +1 -1
  52. data/smoke/rescue/a.rb +4 -13
  53. data/steep.gemspec +1 -1
  54. metadata +5 -5
@@ -17,15 +17,14 @@ module Steep
17
17
  @rest_keywords = rest_keywords
18
18
  end
19
19
 
20
- NONE = Object.new
21
- def update(required: NONE, optional: NONE, rest: NONE, required_keywords: NONE, optional_keywords: NONE, rest_keywords: NONE)
20
+ def update(required: self.required, optional: self.optional, rest: self.rest, required_keywords: self.required_keywords, optional_keywords: self.optional_keywords, rest_keywords: self.rest_keywords)
22
21
  self.class.new(
23
- required: required.equal?(NONE) ? self.required : required,
24
- optional: optional.equal?(NONE) ? self.optional : optional,
25
- rest: rest.equal?(NONE) ? self.rest : rest,
26
- required_keywords: required_keywords.equal?(NONE) ? self.required_keywords : required_keywords,
27
- optional_keywords: optional_keywords.equal?(NONE) ? self.optional_keywords : optional_keywords,
28
- rest_keywords: rest_keywords.equal?(NONE) ? self.rest_keywords : rest_keywords
22
+ required: required,
23
+ optional: optional,
24
+ rest: rest,
25
+ required_keywords: required_keywords,
26
+ optional_keywords: optional_keywords,
27
+ rest_keywords: rest_keywords,
29
28
  )
30
29
  end
31
30
 
@@ -84,6 +83,12 @@ module Steep
84
83
  other.rest_keywords == rest_keywords
85
84
  end
86
85
 
86
+ alias eql? ==
87
+
88
+ def hash
89
+ required.hash ^ optional.hash ^ rest.hash ^ required_keywords.hash ^ optional_keywords.hash ^ rest_keywords.hash
90
+ end
91
+
87
92
  def flat_unnamed_params
88
93
  required.map {|p| [:required, p] } + optional.map {|p| [:optional, p] }
89
94
  end
@@ -211,10 +216,10 @@ module Steep
211
216
  end
212
217
  end
213
218
 
214
- def free_variables
215
- Set.new.tap do |fvs|
219
+ def free_variables()
220
+ @fvs ||= Set.new.tap do |set|
216
221
  each_type do |type|
217
- fvs.merge type.free_variables
222
+ set.merge(type.free_variables)
218
223
  end
219
224
  end
220
225
  end
@@ -224,14 +229,29 @@ module Steep
224
229
  end
225
230
 
226
231
  def subst(s)
227
- self.class.new(
228
- required: required.map {|t| t.subst(s) },
229
- optional: optional.map {|t| t.subst(s) },
230
- rest: rest&.subst(s),
231
- required_keywords: required_keywords.transform_values {|t| t.subst(s) },
232
- optional_keywords: optional_keywords.transform_values {|t| t.subst(s) },
233
- rest_keywords: rest_keywords&.subst(s)
234
- )
232
+ return self if s.empty?
233
+ return self if empty?
234
+ return self if free_variables.disjoint?(s.domain)
235
+
236
+ rs = required.map {|t| t.subst(s) }
237
+ os = optional.map {|t| t.subst(s) }
238
+ r = rest&.subst(s)
239
+ rk = required_keywords.transform_values {|t| t.subst(s) }
240
+ ok = optional_keywords.transform_values {|t| t.subst(s) }
241
+ k = rest_keywords&.subst(s)
242
+
243
+ if rs == required && os == optional && r == rest && rk == required_keywords && ok == optional_keywords && k == rest_keywords
244
+ self
245
+ else
246
+ self.class.new(
247
+ required: required.map {|t| t.subst(s) },
248
+ optional: optional.map {|t| t.subst(s) },
249
+ rest: rest&.subst(s),
250
+ required_keywords: required_keywords.transform_values {|t| t.subst(s) },
251
+ optional_keywords: optional_keywords.transform_values {|t| t.subst(s) },
252
+ rest_keywords: rest_keywords&.subst(s)
253
+ )
254
+ end
235
255
  end
236
256
 
237
257
  def size
@@ -263,59 +283,61 @@ module Steep
263
283
  !has_positional? && !has_keywords?
264
284
  end
265
285
 
266
- def |(other)
286
+ # self + params returns a new params for overloading.
287
+ #
288
+ def +(other)
267
289
  a = first_param
268
290
  b = other.first_param
269
291
 
270
292
  case
271
293
  when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
272
294
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
273
- (self.drop_first | other.drop_first).with_first_param(RequiredPositional.new(type))
295
+ (self.drop_first + other.drop_first).with_first_param(RequiredPositional.new(type))
274
296
  end
275
297
  when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
276
298
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
277
- (self.drop_first | other.drop_first).with_first_param(OptionalPositional.new(type))
299
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
278
300
  end
279
301
  when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
280
302
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
281
- (self.drop_first | other).with_first_param(OptionalPositional.new(type))
303
+ (self.drop_first + other).with_first_param(OptionalPositional.new(type))
282
304
  end
283
305
  when a.is_a?(RequiredPositional) && b.nil?
284
- (self.drop_first | other).with_first_param(OptionalPositional.new(a.type))
306
+ (self.drop_first + other).with_first_param(OptionalPositional.new(a.type))
285
307
  when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
286
308
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
287
- (self.drop_first | other.drop_first).with_first_param(OptionalPositional.new(type))
309
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
288
310
  end
289
311
  when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
290
312
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
291
- (self.drop_first | other.drop_first).with_first_param(OptionalPositional.new(type))
313
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
292
314
  end
293
315
  when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
294
316
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
295
- (self.drop_first | other).with_first_param(OptionalPositional.new(type))
317
+ (self.drop_first + other).with_first_param(OptionalPositional.new(type))
296
318
  end
297
319
  when a.is_a?(OptionalPositional) && b.nil?
298
- (self.drop_first | other).with_first_param(OptionalPositional.new(a.type))
320
+ (self.drop_first + other).with_first_param(OptionalPositional.new(a.type))
299
321
  when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
300
322
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
301
- (self | other.drop_first).with_first_param(OptionalPositional.new(type))
323
+ (self + other.drop_first).with_first_param(OptionalPositional.new(type))
302
324
  end
303
325
  when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
304
326
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
305
- (self | other.drop_first).with_first_param(OptionalPositional.new(type))
327
+ (self + other.drop_first).with_first_param(OptionalPositional.new(type))
306
328
  end
307
329
  when a.is_a?(RestPositional) && b.is_a?(RestPositional)
308
330
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
309
- (self.drop_first | other.drop_first).with_first_param(RestPositional.new(type))
331
+ (self.drop_first + other.drop_first).with_first_param(RestPositional.new(type))
310
332
  end
311
333
  when a.is_a?(RestPositional) && b.nil?
312
- (self.drop_first | other).with_first_param(RestPositional.new(a.type))
334
+ (self.drop_first + other).with_first_param(RestPositional.new(a.type))
313
335
  when a.nil? && b.is_a?(RequiredPositional)
314
- (self | other.drop_first).with_first_param(OptionalPositional.new(b.type))
336
+ (self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
315
337
  when a.nil? && b.is_a?(OptionalPositional)
316
- (self | other.drop_first).with_first_param(OptionalPositional.new(b.type))
338
+ (self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
317
339
  when a.nil? && b.is_a?(RestPositional)
318
- (self | other.drop_first).with_first_param(RestPositional.new(b.type))
340
+ (self + other.drop_first).with_first_param(RestPositional.new(b.type))
319
341
  when a.nil? && b.nil?
320
342
  required_keywords = {}
321
343
 
@@ -395,6 +417,9 @@ module Steep
395
417
  end
396
418
  end
397
419
 
420
+ # Returns the intersection between self and other.
421
+ # Returns nil if the intersection cannot be computed.
422
+ #
398
423
  def &(other)
399
424
  a = first_param
400
425
  b = other.first_param
@@ -402,48 +427,48 @@ module Steep
402
427
  case
403
428
  when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
404
429
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
405
- (self.drop_first & other.drop_first).with_first_param(RequiredPositional.new(type))
430
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
406
431
  end
407
432
  when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
408
433
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
409
- (self.drop_first & other.drop_first).with_first_param(RequiredPositional.new(type))
434
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
410
435
  end
411
436
  when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
412
437
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
413
- (self.drop_first & other).with_first_param(RequiredPositional.new(type))
438
+ (self.drop_first & other)&.with_first_param(RequiredPositional.new(type))
414
439
  end
415
440
  when a.is_a?(RequiredPositional) && b.nil?
416
- (self.drop_first & other).with_first_param(RequiredPositional.new(AST::Types::Bot.new))
441
+ nil
417
442
  when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
418
443
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
419
- (self.drop_first & other.drop_first).with_first_param(RequiredPositional.new(type))
444
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
420
445
  end
421
446
  when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
422
447
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
423
- (self.drop_first & other.drop_first).with_first_param(OptionalPositional.new(type))
448
+ (self.drop_first & other.drop_first)&.with_first_param(OptionalPositional.new(type))
424
449
  end
425
450
  when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
426
451
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
427
- (self.drop_first & other).with_first_param(OptionalPositional.new(type))
452
+ (self.drop_first & other)&.with_first_param(OptionalPositional.new(type))
428
453
  end
429
454
  when a.is_a?(OptionalPositional) && b.nil?
430
455
  self.drop_first & other
431
456
  when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
432
457
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
433
- (self & other.drop_first).with_first_param(RequiredPositional.new(type))
458
+ (self & other.drop_first)&.with_first_param(RequiredPositional.new(type))
434
459
  end
435
460
  when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
436
461
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
437
- (self & other.drop_first).with_first_param(OptionalPositional.new(type))
462
+ (self & other.drop_first)&.with_first_param(OptionalPositional.new(type))
438
463
  end
439
464
  when a.is_a?(RestPositional) && b.is_a?(RestPositional)
440
465
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
441
- (self.drop_first & other.drop_first).with_first_param(RestPositional.new(type))
466
+ (self.drop_first & other.drop_first)&.with_first_param(RestPositional.new(type))
442
467
  end
443
468
  when a.is_a?(RestPositional) && b.nil?
444
469
  self.drop_first & other
445
470
  when a.nil? && b.is_a?(RequiredPositional)
446
- (self & other.drop_first).with_first_param(RequiredPositional.new(AST::Types::Bot.new))
471
+ nil
447
472
  when a.nil? && b.is_a?(OptionalPositional)
448
473
  self & other.drop_first
449
474
  when a.nil? && b.is_a?(RestPositional)
@@ -452,7 +477,7 @@ module Steep
452
477
  optional_keywords = {}
453
478
 
454
479
  (Set.new(self.optional_keywords.keys) & Set.new(other.optional_keywords.keys)).each do |keyword|
455
- self.optional_keywords[keyword] = AST::Types::Intersection.build(
480
+ optional_keywords[keyword] = AST::Types::Intersection.build(
456
481
  types: [
457
482
  self.optional_keywords[keyword],
458
483
  other.optional_keywords[keyword]
@@ -467,9 +492,7 @@ module Steep
467
492
  when other.required_keywords.key?(keyword)
468
493
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.required_keywords[keyword]])
469
494
  when other.rest_keywords
470
- required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
471
- else
472
- required_keywords[keyword] = t
495
+ optional_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
473
496
  end
474
497
  end
475
498
  end
@@ -479,9 +502,7 @@ module Steep
479
502
  when self.required_keywords.key?(keyword)
480
503
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.required_keywords[keyword]])
481
504
  when self.rest_keywords
482
- required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
483
- else
484
- required_keywords[keyword] = t
505
+ optional_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
485
506
  end
486
507
  end
487
508
  end
@@ -493,7 +514,7 @@ module Steep
493
514
  when other.rest_keywords
494
515
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
495
516
  else
496
- required_keywords[keyword] = t
517
+ return
497
518
  end
498
519
  end
499
520
  end
@@ -505,7 +526,7 @@ module Steep
505
526
  when self.rest_keywords
506
527
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
507
528
  else
508
- required_keywords[keyword] = t
529
+ return
509
530
  end
510
531
  end
511
532
  end
@@ -514,7 +535,153 @@ module Steep
514
535
  when self.rest_keywords && other.rest_keywords
515
536
  AST::Types::Intersection.build(types: [self.rest_keywords, other.rest_keywords])
516
537
  else
517
- self.rest_keywords || other.rest_keywords
538
+ nil
539
+ end
540
+
541
+ Params.new(
542
+ required: [],
543
+ optional: [],
544
+ rest: nil,
545
+ required_keywords: required_keywords,
546
+ optional_keywords: optional_keywords,
547
+ rest_keywords: rest)
548
+ end
549
+ end
550
+
551
+ # Returns the union between self and other.
552
+ #
553
+ def |(other)
554
+ a = first_param
555
+ b = other.first_param
556
+
557
+ case
558
+ when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
559
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
560
+ (self.drop_first | other.drop_first)&.with_first_param(RequiredPositional.new(type))
561
+ end
562
+ when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
563
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
564
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
565
+ end
566
+ when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
567
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
568
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
569
+ end
570
+ when a.is_a?(RequiredPositional) && b.nil?
571
+ self.drop_first&.with_first_param(OptionalPositional.new(a.type))
572
+ when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
573
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
574
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
575
+ end
576
+ when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
577
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
578
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
579
+ end
580
+ when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
581
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
582
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
583
+ end
584
+ when a.is_a?(OptionalPositional) && b.nil?
585
+ (self.drop_first | other)&.with_first_param(a)
586
+ when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
587
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
588
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
589
+ end
590
+ when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
591
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
592
+ (self | other.drop_first)&.with_first_param(OptionalPositional.new(type))
593
+ end
594
+ when a.is_a?(RestPositional) && b.is_a?(RestPositional)
595
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
596
+ (self.drop_first | other.drop_first)&.with_first_param(RestPositional.new(type))
597
+ end
598
+ when a.is_a?(RestPositional) && b.nil?
599
+ (self.drop_first | other)&.with_first_param(a)
600
+ when a.nil? && b.is_a?(RequiredPositional)
601
+ other.drop_first&.with_first_param(OptionalPositional.new(b.type))
602
+ when a.nil? && b.is_a?(OptionalPositional)
603
+ (self | other.drop_first)&.with_first_param(b)
604
+ when a.nil? && b.is_a?(RestPositional)
605
+ (self | other.drop_first)&.with_first_param(b)
606
+ when a.nil? && b.nil?
607
+ required_keywords = {}
608
+ optional_keywords = {}
609
+
610
+ (Set.new(self.required_keywords.keys) & Set.new(other.required_keywords.keys)).each do |keyword|
611
+ required_keywords[keyword] = AST::Types::Union.build(
612
+ types: [
613
+ self.required_keywords[keyword],
614
+ other.required_keywords[keyword]
615
+ ]
616
+ )
617
+ end
618
+
619
+ self.optional_keywords.each do |keyword, t|
620
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
621
+ case
622
+ when s = other.required_keywords[keyword]
623
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
624
+ when s = other.optional_keywords[keyword]
625
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
626
+ when r = other.rest_keywords
627
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
628
+ else
629
+ optional_keywords[keyword] = t
630
+ end
631
+ end
632
+ end
633
+ other.optional_keywords.each do |keyword, t|
634
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
635
+ case
636
+ when s = self.required_keywords[keyword]
637
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
638
+ when s = self.optional_keywords[keyword]
639
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
640
+ when r = self.rest_keywords
641
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
642
+ else
643
+ optional_keywords[keyword] = t
644
+ end
645
+ end
646
+ end
647
+ self.required_keywords.each do |keyword, t|
648
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
649
+ case
650
+ when s = other.optional_keywords[keyword]
651
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
652
+ when r = other.rest_keywords
653
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
654
+ else
655
+ optional_keywords[keyword] = t
656
+ end
657
+ end
658
+ end
659
+ other.required_keywords.each do |keyword, t|
660
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
661
+ case
662
+ when s = self.optional_keywords[keyword]
663
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
664
+ when r = self.rest_keywords
665
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
666
+ else
667
+ optional_keywords[keyword] = t
668
+ end
669
+ end
670
+ end
671
+
672
+ rest = case
673
+ when self.rest_keywords && other.rest_keywords
674
+ AST::Types::Union.build(types: [self.rest_keywords, other.rest_keywords])
675
+ when self.rest_keywords
676
+ if required_keywords.empty? && optional_keywords.empty?
677
+ self.rest_keywords
678
+ end
679
+ when other.rest_keywords
680
+ if required_keywords.empty? && optional_keywords.empty?
681
+ other.rest_keywords
682
+ end
683
+ else
684
+ nil
518
685
  end
519
686
 
520
687
  Params.new(
@@ -552,19 +719,30 @@ module Steep
552
719
  other.is_a?(self.class) && other.type == type && other.optional == optional
553
720
  end
554
721
 
722
+ alias eql? ==
723
+
724
+ def hash
725
+ type.hash ^ optional.hash
726
+ end
727
+
555
728
  def closed?
556
729
  type.closed?
557
730
  end
558
731
 
559
732
  def subst(s)
560
- self.class.new(
561
- type: type.subst(s),
562
- optional: optional
563
- )
733
+ ty = type.subst(s)
734
+ if ty == type
735
+ self
736
+ else
737
+ self.class.new(
738
+ type: ty,
739
+ optional: optional
740
+ )
741
+ end
564
742
  end
565
743
 
566
- def free_variables
567
- type.free_variables
744
+ def free_variables()
745
+ @fvs ||= type.free_variables
568
746
  end
569
747
 
570
748
  def to_s
@@ -580,9 +758,10 @@ module Steep
580
758
 
581
759
  def +(other)
582
760
  optional = self.optional? || other.optional?
583
- type = AST::Types::Proc.new(params: self.type.params | other.type.params,
584
- return_type: AST::Types::Union.build(types: [self.type.return_type,
585
- other.type.return_type]))
761
+ type = AST::Types::Proc.new(
762
+ params: self.type.params + other.type.params,
763
+ return_type: AST::Types::Union.build(types: [self.type.return_type, other.type.return_type])
764
+ )
586
765
  self.class.new(
587
766
  type: type,
588
767
  optional: optional
@@ -597,8 +776,6 @@ module Steep
597
776
  attr_reader :return_type
598
777
  attr_reader :location
599
778
 
600
- NONE = Object.new
601
-
602
779
  def initialize(type_params:, params:, block:, return_type:, location:)
603
780
  @type_params = type_params
604
781
  @params = params
@@ -616,11 +793,27 @@ module Steep
616
793
  (!other.location || !location || other.location == location)
617
794
  end
618
795
 
796
+ alias eql? ==
797
+
798
+ def hash
799
+ type_params.hash ^ params.hash ^ block.hash ^ return_type.hash
800
+ end
801
+
619
802
  def free_variables
620
- (params.free_variables + (block&.free_variables || Set.new) + return_type.free_variables) - Set.new(type_params)
803
+ @fvs ||= Set.new.tap do |set|
804
+ set.merge(params.free_variables)
805
+ if block
806
+ set.merge(block.free_variables)
807
+ end
808
+ set.merge(return_type.free_variables)
809
+ set.subtract(type_params)
810
+ end
621
811
  end
622
812
 
623
813
  def subst(s)
814
+ return self if s.empty?
815
+ return self if free_variables.disjoint?(s.domain)
816
+
624
817
  s_ = s.except(type_params)
625
818
 
626
819
  self.class.new(
@@ -646,23 +839,19 @@ module Steep
646
839
  end
647
840
 
648
841
  def instantiate(s)
649
- self.class.new(
650
- type_params: [],
651
- params: params.subst(s),
652
- block: block&.subst(s),
653
- return_type: return_type.subst(s),
654
- location: location,
655
- )
842
+ self.class.new(type_params: [],
843
+ params: params.subst(s),
844
+ block: block&.subst(s),
845
+ return_type: return_type.subst(s),
846
+ location: location)
656
847
  end
657
848
 
658
- def with(type_params: NONE, params: NONE, block: NONE, return_type: NONE, location: NONE)
659
- self.class.new(
660
- type_params: type_params.equal?(NONE) ? self.type_params : type_params,
661
- params: params.equal?(NONE) ? self.params : params,
662
- block: block.equal?(NONE) ? self.block : block,
663
- return_type: return_type.equal?(NONE) ? self.return_type : return_type,
664
- location: location.equal?(NONE) ? self.location : location
665
- )
849
+ def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type, location: self.location)
850
+ self.class.new(type_params: type_params,
851
+ params: params,
852
+ block: block,
853
+ return_type: return_type,
854
+ location: location)
666
855
  end
667
856
 
668
857
  def to_s
@@ -674,16 +863,16 @@ module Steep
674
863
  end
675
864
 
676
865
  def map_type(&block)
677
- self.class.new(
678
- type_params: type_params,
679
- params: params.map_type(&block),
680
- block: self.block&.yield_self {|blk| blk.map_type(&block) },
681
- return_type: yield(return_type),
682
- location: location
683
- )
866
+ self.class.new(type_params: type_params,
867
+ params: params.map_type(&block),
868
+ block: self.block&.yield_self {|blk| blk.map_type(&block) },
869
+ return_type: yield(return_type),
870
+ location: location)
684
871
  end
685
872
 
686
- def +(other)
873
+ # Returns a new method type which can be used for the method implementation type of both `self` and `other`.
874
+ #
875
+ def unify_overload(other)
687
876
  type_params = []
688
877
  s1 = Substitution.build(self.type_params)
689
878
  type_params.push(*s1.dictionary.values.map(&:name))
@@ -701,7 +890,7 @@ module Steep
701
890
 
702
891
  self.class.new(
703
892
  type_params: type_params,
704
- params: params.subst(s1) | other.params.subst(s2),
893
+ params: params.subst(s1) + other.params.subst(s2),
705
894
  block: block,
706
895
  return_type: AST::Types::Union.build(
707
896
  types: [return_type.subst(s1),other.return_type.subst(s2)]
@@ -709,6 +898,108 @@ module Steep
709
898
  location: nil
710
899
  )
711
900
  end
901
+
902
+ def +(other)
903
+ unify_overload(other)
904
+ end
905
+
906
+ # Returns a method type which is a super-type of both self and other.
907
+ # self <: (self | other) && other <: (self | other)
908
+ #
909
+ # Returns nil if self and other are incompatible.
910
+ #
911
+ def |(other)
912
+ self_type_params = Set.new(self.type_params)
913
+ other_type_params = Set.new(other.type_params)
914
+
915
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
916
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
917
+ fresh_names = fresh_types.map(&:name)
918
+ subst = Substitution.build(common_type_params, fresh_types)
919
+ other = other.instantiate(subst)
920
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
921
+ else
922
+ type_params = (self_type_params + other_type_params).to_a
923
+ end
924
+
925
+ params = self.params & other.params or return
926
+ block = case
927
+ when self.block && other.block
928
+ block_params = self.block.type.params | other.block.type.params
929
+ block_return_type = AST::Types::Intersection.build(types: [self.block.type.return_type, other.block.type.return_type])
930
+ block_type = AST::Types::Proc.new(params: block_params,
931
+ return_type: block_return_type,
932
+ location: nil)
933
+ Block.new(
934
+ type: block_type,
935
+ optional: self.block.optional && other.block.optional
936
+ )
937
+ when self.block && self.block.optional?
938
+ self.block
939
+ when other.block && other.block.optional?
940
+ other.block
941
+ when !self.block && !other.block
942
+ nil
943
+ else
944
+ return
945
+ end
946
+ return_type = AST::Types::Union.build(types: [self.return_type, other.return_type])
947
+
948
+ MethodType.new(
949
+ params: params,
950
+ block: block,
951
+ return_type: return_type,
952
+ type_params: type_params,
953
+ location: nil
954
+ )
955
+ end
956
+
957
+ # Returns a method type which is a sub-type of both self and other.
958
+ # (self & other) <: self && (self & other) <: other
959
+ #
960
+ # Returns nil if self and other are incompatible.
961
+ #
962
+ def &(other)
963
+ self_type_params = Set.new(self.type_params)
964
+ other_type_params = Set.new(other.type_params)
965
+
966
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
967
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
968
+ fresh_names = fresh_types.map(&:name)
969
+ subst = Substitution.build(common_type_params, fresh_types)
970
+ other = other.subst(subst)
971
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
972
+ else
973
+ type_params = (self_type_params + other_type_params).to_a
974
+ end
975
+
976
+ params = self.params | other.params
977
+ block = case
978
+ when self.block && other.block
979
+ block_params = self.block.type.params & other.block.type.params or return
980
+ block_return_type = AST::Types::Union.build(types: [self.block.type.return_type, other.block.type.return_type])
981
+ block_type = AST::Types::Proc.new(params: block_params,
982
+ return_type: block_return_type,
983
+ location: nil)
984
+ Block.new(
985
+ type: block_type,
986
+ optional: self.block.optional || other.block.optional
987
+ )
988
+
989
+ else
990
+ self.block || other.block
991
+ end
992
+
993
+ return_type = AST::Types::Intersection.build(types: [self.return_type, other.return_type])
994
+
995
+ MethodType.new(
996
+ params: params,
997
+ block: block,
998
+ return_type: return_type,
999
+ type_params: type_params,
1000
+ location: nil
1001
+ )
1002
+ end
712
1003
  end
713
1004
  end
714
1005
  end