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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -1
- data/bin/smoke_runner.rb +3 -4
- data/lib/steep.rb +1 -1
- data/lib/steep/ast/builtin.rb +2 -20
- data/lib/steep/ast/types.rb +5 -3
- data/lib/steep/ast/types/any.rb +1 -3
- data/lib/steep/ast/types/boolean.rb +1 -3
- data/lib/steep/ast/types/bot.rb +1 -3
- data/lib/steep/ast/types/class.rb +2 -2
- data/lib/steep/ast/types/factory.rb +106 -55
- data/lib/steep/ast/types/helper.rb +6 -0
- data/lib/steep/ast/types/instance.rb +2 -2
- data/lib/steep/ast/types/intersection.rb +20 -13
- data/lib/steep/ast/types/literal.rb +1 -3
- data/lib/steep/ast/types/name.rb +15 -67
- data/lib/steep/ast/types/nil.rb +1 -3
- data/lib/steep/ast/types/proc.rb +5 -2
- data/lib/steep/ast/types/record.rb +9 -4
- data/lib/steep/ast/types/self.rb +1 -1
- data/lib/steep/ast/types/top.rb +1 -3
- data/lib/steep/ast/types/tuple.rb +5 -3
- data/lib/steep/ast/types/union.rb +16 -9
- data/lib/steep/ast/types/var.rb +2 -2
- data/lib/steep/ast/types/void.rb +1 -3
- data/lib/steep/drivers/check.rb +4 -0
- data/lib/steep/errors.rb +14 -0
- data/lib/steep/interface/interface.rb +5 -62
- data/lib/steep/interface/method_type.rb +383 -92
- data/lib/steep/interface/substitution.rb +48 -6
- data/lib/steep/project/completion_provider.rb +1 -1
- data/lib/steep/project/hover_content.rb +1 -1
- data/lib/steep/project/target.rb +5 -2
- data/lib/steep/server/base_worker.rb +5 -3
- data/lib/steep/server/code_worker.rb +2 -0
- data/lib/steep/server/master.rb +10 -1
- data/lib/steep/source.rb +4 -3
- data/lib/steep/subtyping/check.rb +49 -60
- data/lib/steep/type_construction.rb +629 -366
- data/lib/steep/type_inference/block_params.rb +5 -0
- data/lib/steep/type_inference/constant_env.rb +1 -1
- data/lib/steep/type_inference/context.rb +8 -0
- data/lib/steep/type_inference/context_array.rb +4 -3
- data/lib/steep/type_inference/logic.rb +31 -0
- data/lib/steep/typing.rb +7 -0
- data/lib/steep/version.rb +1 -1
- data/smoke/alias/a.rb +1 -1
- data/smoke/case/a.rb +1 -1
- data/smoke/hash/d.rb +1 -1
- data/smoke/if/a.rb +1 -1
- data/smoke/module/a.rb +1 -1
- data/smoke/rescue/a.rb +4 -13
- data/steep.gemspec +1 -1
- metadata +5 -5
@@ -17,15 +17,14 @@ module Steep
|
|
17
17
|
@rest_keywords = rest_keywords
|
18
18
|
end
|
19
19
|
|
20
|
-
|
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
|
24
|
-
optional: optional
|
25
|
-
rest: rest
|
26
|
-
required_keywords: required_keywords
|
27
|
-
optional_keywords: optional_keywords
|
28
|
-
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 |
|
219
|
+
def free_variables()
|
220
|
+
@fvs ||= Set.new.tap do |set|
|
216
221
|
each_type do |type|
|
217
|
-
|
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.
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
334
|
+
(self.drop_first + other).with_first_param(RestPositional.new(a.type))
|
313
335
|
when a.nil? && b.is_a?(RequiredPositional)
|
314
|
-
(self
|
336
|
+
(self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
|
315
337
|
when a.nil? && b.is_a?(OptionalPositional)
|
316
|
-
(self
|
338
|
+
(self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
|
317
339
|
when a.nil? && b.is_a?(RestPositional)
|
318
|
-
(self
|
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)
|
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)
|
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)
|
438
|
+
(self.drop_first & other)&.with_first_param(RequiredPositional.new(type))
|
414
439
|
end
|
415
440
|
when a.is_a?(RequiredPositional) && b.nil?
|
416
|
-
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
561
|
-
|
562
|
-
|
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(
|
584
|
-
|
585
|
-
|
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
|
-
|
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
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
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:
|
659
|
-
self.class.new(
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
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
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
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
|
-
|
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)
|
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
|