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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/bin/smoke_runner.rb +3 -4
- data/lib/steep.rb +4 -3
- data/lib/steep/annotation_parser.rb +2 -4
- data/lib/steep/ast/builtin.rb +11 -21
- 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 +249 -89
- 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/logic.rb +63 -0
- 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 +394 -93
- data/lib/steep/interface/substitution.rb +48 -6
- data/lib/steep/module_helper.rb +25 -0
- data/lib/steep/project/completion_provider.rb +48 -51
- data/lib/steep/project/file.rb +3 -3
- data/lib/steep/project/hover_content.rb +4 -6
- 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/signature/validator.rb +3 -3
- data/lib/steep/source.rb +4 -3
- data/lib/steep/subtyping/check.rb +46 -59
- data/lib/steep/subtyping/constraints.rb +8 -0
- data/lib/steep/type_construction.rb +771 -513
- data/lib/steep/type_inference/block_params.rb +5 -0
- data/lib/steep/type_inference/constant_env.rb +3 -6
- 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/type_inference/logic_type_interpreter.rb +219 -0
- data/lib/steep/type_inference/type_env.rb +2 -2
- 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/smoke/type_case/a.rb +0 -7
- data/steep.gemspec +2 -2
- metadata +10 -10
- data/lib/steep/ast/method_type.rb +0 -126
- data/lib/steep/ast/namespace.rb +0 -80
- data/lib/steep/names.rb +0 -86
data/lib/steep/drivers/check.rb
CHANGED
data/lib/steep/errors.rb
CHANGED
@@ -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
|
5
|
-
attr_reader :
|
6
|
-
attr_reader :types
|
4
|
+
class Entry
|
5
|
+
attr_reader :method_types
|
7
6
|
|
8
|
-
def initialize(
|
9
|
-
@
|
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
|
-
|
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
|
-
|
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
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
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:
|
659
|
-
self.class.new(
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
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
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
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
|
-
|
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)
|
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
|