steep 0.23.0 → 0.29.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/bin/smoke_runner.rb +3 -4
  4. data/lib/steep.rb +4 -3
  5. data/lib/steep/annotation_parser.rb +2 -4
  6. data/lib/steep/ast/builtin.rb +11 -21
  7. data/lib/steep/ast/types.rb +5 -3
  8. data/lib/steep/ast/types/any.rb +1 -3
  9. data/lib/steep/ast/types/boolean.rb +1 -3
  10. data/lib/steep/ast/types/bot.rb +1 -3
  11. data/lib/steep/ast/types/class.rb +2 -2
  12. data/lib/steep/ast/types/factory.rb +249 -89
  13. data/lib/steep/ast/types/helper.rb +6 -0
  14. data/lib/steep/ast/types/instance.rb +2 -2
  15. data/lib/steep/ast/types/intersection.rb +20 -13
  16. data/lib/steep/ast/types/literal.rb +1 -3
  17. data/lib/steep/ast/types/logic.rb +63 -0
  18. data/lib/steep/ast/types/name.rb +15 -67
  19. data/lib/steep/ast/types/nil.rb +1 -3
  20. data/lib/steep/ast/types/proc.rb +5 -2
  21. data/lib/steep/ast/types/record.rb +9 -4
  22. data/lib/steep/ast/types/self.rb +1 -1
  23. data/lib/steep/ast/types/top.rb +1 -3
  24. data/lib/steep/ast/types/tuple.rb +5 -3
  25. data/lib/steep/ast/types/union.rb +16 -9
  26. data/lib/steep/ast/types/var.rb +2 -2
  27. data/lib/steep/ast/types/void.rb +1 -3
  28. data/lib/steep/drivers/check.rb +4 -0
  29. data/lib/steep/errors.rb +14 -0
  30. data/lib/steep/interface/interface.rb +5 -62
  31. data/lib/steep/interface/method_type.rb +394 -93
  32. data/lib/steep/interface/substitution.rb +48 -6
  33. data/lib/steep/module_helper.rb +25 -0
  34. data/lib/steep/project/completion_provider.rb +48 -51
  35. data/lib/steep/project/file.rb +3 -3
  36. data/lib/steep/project/hover_content.rb +4 -6
  37. data/lib/steep/project/target.rb +5 -2
  38. data/lib/steep/server/base_worker.rb +5 -3
  39. data/lib/steep/server/code_worker.rb +2 -0
  40. data/lib/steep/server/master.rb +10 -1
  41. data/lib/steep/signature/validator.rb +3 -3
  42. data/lib/steep/source.rb +4 -3
  43. data/lib/steep/subtyping/check.rb +46 -59
  44. data/lib/steep/subtyping/constraints.rb +8 -0
  45. data/lib/steep/type_construction.rb +771 -513
  46. data/lib/steep/type_inference/block_params.rb +5 -0
  47. data/lib/steep/type_inference/constant_env.rb +3 -6
  48. data/lib/steep/type_inference/context.rb +8 -0
  49. data/lib/steep/type_inference/context_array.rb +4 -3
  50. data/lib/steep/type_inference/logic.rb +31 -0
  51. data/lib/steep/type_inference/logic_type_interpreter.rb +219 -0
  52. data/lib/steep/type_inference/type_env.rb +2 -2
  53. data/lib/steep/typing.rb +7 -0
  54. data/lib/steep/version.rb +1 -1
  55. data/smoke/alias/a.rb +1 -1
  56. data/smoke/case/a.rb +1 -1
  57. data/smoke/hash/d.rb +1 -1
  58. data/smoke/if/a.rb +1 -1
  59. data/smoke/module/a.rb +1 -1
  60. data/smoke/rescue/a.rb +4 -13
  61. data/smoke/type_case/a.rb +0 -7
  62. data/steep.gemspec +2 -2
  63. metadata +10 -10
  64. data/lib/steep/ast/method_type.rb +0 -126
  65. data/lib/steep/ast/namespace.rb +0 -80
  66. data/lib/steep/names.rb +0 -86
@@ -60,6 +60,10 @@ module Steep
60
60
  Steep.log_error source_file.status.error
61
61
  end
62
62
  end
63
+ when Project::Target::SignatureOtherErrorStatus
64
+ Steep.log_error status.error
65
+ else
66
+ Steep.logger.error { "Unexpected status: #{status.class}" }
63
67
  end
64
68
  end
65
69
  end
@@ -543,5 +543,19 @@ module Steep
543
543
  "#{location_to_str}: MissingKeyword: #{missing_keywords.to_a.join(", ")}"
544
544
  end
545
545
  end
546
+
547
+ class UnsupportedSyntax < Base
548
+ attr_reader :message
549
+
550
+ def initialize(node:, message: nil)
551
+ super(node: node)
552
+ @message = message
553
+ end
554
+
555
+ def to_s
556
+ msg = message || "#{node.type} is not supported"
557
+ "#{location_to_str}: UnsupportedSyntax: #{msg}"
558
+ end
559
+ end
546
560
  end
547
561
  end
@@ -1,72 +1,15 @@
1
1
  module Steep
2
2
  module Interface
3
3
  class Interface
4
- class Combination
5
- attr_reader :operator
6
- attr_reader :types
4
+ class Entry
5
+ attr_reader :method_types
7
6
 
8
- def initialize(operator:, types:)
9
- @types = types
10
- @operator = operator
11
- @incompatible = false
12
- end
13
-
14
- def overload?
15
- operator == :overload
16
- end
17
-
18
- def union?
19
- operator == :union
20
- end
21
-
22
- def intersection?
23
- operator == :intersection
24
- end
25
-
26
- def self.overload(types, incompatible:)
27
- new(operator: :overload, types: types).incompatible!(incompatible)
28
- end
29
-
30
- def incompatible?
31
- @incompatible
32
- end
33
-
34
- def incompatible!(value)
35
- @incompatible = value
36
- self
37
- end
38
-
39
- def self.union(types)
40
- case types.size
41
- when 0
42
- raise "Combination.union called with zero types"
43
- when 1
44
- types.first
45
- else
46
- new(operator: :union, types: types)
47
- end
48
- end
49
-
50
- def self.intersection(types)
51
- case types.size
52
- when 0
53
- raise "Combination.intersection called with zero types"
54
- when 1
55
- types.first
56
- else
57
- new(operator: :intersection, types: types)
58
- end
7
+ def initialize(method_types:)
8
+ @method_types = method_types
59
9
  end
60
10
 
61
11
  def to_s
62
- case operator
63
- when :overload
64
- "{ #{types.map(&:to_s).join(" | ")} }"
65
- when :union
66
- "[#{types.map(&:to_s).join(" | ")}]"
67
- when :intersection
68
- "[#{types.map(&:to_s).join(" & ")}]"
69
- end
12
+ "{ #{method_types.join(" || ")} }"
70
13
  end
71
14
  end
72
15
 
@@ -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
@@ -596,15 +775,15 @@ module Steep
596
775
  attr_reader :block
597
776
  attr_reader :return_type
598
777
  attr_reader :location
778
+ attr_reader :method_def
599
779
 
600
- NONE = Object.new
601
-
602
- def initialize(type_params:, params:, block:, return_type:, location:)
780
+ def initialize(type_params:, params:, block:, return_type:, location:, method_def:)
603
781
  @type_params = type_params
604
782
  @params = params
605
783
  @block = block
606
784
  @return_type = return_type
607
785
  @location = location
786
+ @method_def = method_def
608
787
  end
609
788
 
610
789
  def ==(other)
@@ -613,14 +792,31 @@ module Steep
613
792
  other.params == params &&
614
793
  other.block == block &&
615
794
  other.return_type == return_type &&
795
+ (!other.method_def || !method_def || other.method_def == method_def) &&
616
796
  (!other.location || !location || other.location == location)
617
797
  end
618
798
 
799
+ alias eql? ==
800
+
801
+ def hash
802
+ type_params.hash ^ params.hash ^ block.hash ^ return_type.hash
803
+ end
804
+
619
805
  def free_variables
620
- (params.free_variables + (block&.free_variables || Set.new) + return_type.free_variables) - Set.new(type_params)
806
+ @fvs ||= Set.new.tap do |set|
807
+ set.merge(params.free_variables)
808
+ if block
809
+ set.merge(block.free_variables)
810
+ end
811
+ set.merge(return_type.free_variables)
812
+ set.subtract(type_params)
813
+ end
621
814
  end
622
815
 
623
816
  def subst(s)
817
+ return self if s.empty?
818
+ return self if free_variables.disjoint?(s.domain)
819
+
624
820
  s_ = s.except(type_params)
625
821
 
626
822
  self.class.new(
@@ -628,6 +824,7 @@ module Steep
628
824
  params: params.subst(s_),
629
825
  block: block&.subst(s_),
630
826
  return_type: return_type.subst(s_),
827
+ method_def: method_def,
631
828
  location: location
632
829
  )
633
830
  end
@@ -646,23 +843,21 @@ module Steep
646
843
  end
647
844
 
648
845
  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
- )
846
+ self.class.new(type_params: [],
847
+ params: params.subst(s),
848
+ block: block&.subst(s),
849
+ return_type: return_type.subst(s),
850
+ location: location,
851
+ method_def: method_def)
656
852
  end
657
853
 
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
- )
854
+ def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type, location: self.location, method_def: self.method_def)
855
+ self.class.new(type_params: type_params,
856
+ params: params,
857
+ block: block,
858
+ return_type: return_type,
859
+ method_def: method_def,
860
+ location: location)
666
861
  end
667
862
 
668
863
  def to_s
@@ -674,16 +869,17 @@ module Steep
674
869
  end
675
870
 
676
871
  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
- )
872
+ self.class.new(type_params: type_params,
873
+ params: params.map_type(&block),
874
+ block: self.block&.yield_self {|blk| blk.map_type(&block) },
875
+ return_type: yield(return_type),
876
+ location: location,
877
+ method_def: method_def)
684
878
  end
685
879
 
686
- def +(other)
880
+ # Returns a new method type which can be used for the method implementation type of both `self` and `other`.
881
+ #
882
+ def unify_overload(other)
687
883
  type_params = []
688
884
  s1 = Substitution.build(self.type_params)
689
885
  type_params.push(*s1.dictionary.values.map(&:name))
@@ -701,11 +897,116 @@ module Steep
701
897
 
702
898
  self.class.new(
703
899
  type_params: type_params,
704
- params: params.subst(s1) | other.params.subst(s2),
900
+ params: params.subst(s1) + other.params.subst(s2),
705
901
  block: block,
706
902
  return_type: AST::Types::Union.build(
707
903
  types: [return_type.subst(s1),other.return_type.subst(s2)]
708
904
  ),
905
+ method_def: method_def,
906
+ location: nil
907
+ )
908
+ end
909
+
910
+ def +(other)
911
+ unify_overload(other)
912
+ end
913
+
914
+ # Returns a method type which is a super-type of both self and other.
915
+ # self <: (self | other) && other <: (self | other)
916
+ #
917
+ # Returns nil if self and other are incompatible.
918
+ #
919
+ def |(other)
920
+ self_type_params = Set.new(self.type_params)
921
+ other_type_params = Set.new(other.type_params)
922
+
923
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
924
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
925
+ fresh_names = fresh_types.map(&:name)
926
+ subst = Substitution.build(common_type_params, fresh_types)
927
+ other = other.instantiate(subst)
928
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
929
+ else
930
+ type_params = (self_type_params + other_type_params).to_a
931
+ end
932
+
933
+ params = self.params & other.params or return
934
+ block = case
935
+ when self.block && other.block
936
+ block_params = self.block.type.params | other.block.type.params
937
+ block_return_type = AST::Types::Intersection.build(types: [self.block.type.return_type, other.block.type.return_type])
938
+ block_type = AST::Types::Proc.new(params: block_params,
939
+ return_type: block_return_type,
940
+ location: nil)
941
+ Block.new(
942
+ type: block_type,
943
+ optional: self.block.optional && other.block.optional
944
+ )
945
+ when self.block && self.block.optional?
946
+ self.block
947
+ when other.block && other.block.optional?
948
+ other.block
949
+ when !self.block && !other.block
950
+ nil
951
+ else
952
+ return
953
+ end
954
+ return_type = AST::Types::Union.build(types: [self.return_type, other.return_type])
955
+
956
+ MethodType.new(
957
+ params: params,
958
+ block: block,
959
+ return_type: return_type,
960
+ type_params: type_params,
961
+ method_def: nil,
962
+ location: nil
963
+ )
964
+ end
965
+
966
+ # Returns a method type which is a sub-type of both self and other.
967
+ # (self & other) <: self && (self & other) <: other
968
+ #
969
+ # Returns nil if self and other are incompatible.
970
+ #
971
+ def &(other)
972
+ self_type_params = Set.new(self.type_params)
973
+ other_type_params = Set.new(other.type_params)
974
+
975
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
976
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
977
+ fresh_names = fresh_types.map(&:name)
978
+ subst = Substitution.build(common_type_params, fresh_types)
979
+ other = other.subst(subst)
980
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
981
+ else
982
+ type_params = (self_type_params + other_type_params).to_a
983
+ end
984
+
985
+ params = self.params | other.params
986
+ block = case
987
+ when self.block && other.block
988
+ block_params = self.block.type.params & other.block.type.params or return
989
+ block_return_type = AST::Types::Union.build(types: [self.block.type.return_type, other.block.type.return_type])
990
+ block_type = AST::Types::Proc.new(params: block_params,
991
+ return_type: block_return_type,
992
+ location: nil)
993
+ Block.new(
994
+ type: block_type,
995
+ optional: self.block.optional || other.block.optional
996
+ )
997
+
998
+ else
999
+ self.block || other.block
1000
+ end
1001
+
1002
+ return_type = AST::Types::Intersection.build(types: [self.return_type, other.return_type])
1003
+
1004
+ MethodType.new(
1005
+ params: params,
1006
+ block: block,
1007
+ return_type: return_type,
1008
+ type_params: type_params,
1009
+ method_def: nil,
709
1010
  location: nil
710
1011
  )
711
1012
  end