steep 0.23.0 → 0.29.0

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