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
@@ -28,39 +28,46 @@ module Steep
|
|
28
28
|
else
|
29
29
|
type
|
30
30
|
end
|
31
|
-
end.compact.
|
32
|
-
|
31
|
+
end.compact.yield_self do |tys|
|
32
|
+
dups = Set.new(tys)
|
33
|
+
|
34
|
+
case dups.size
|
35
|
+
when 0
|
36
|
+
AST::Types::Top.new(location: location)
|
37
|
+
when 1
|
33
38
|
tys.first
|
34
39
|
else
|
35
|
-
new(types:
|
40
|
+
new(types: dups.to_a, location: location)
|
36
41
|
end
|
37
42
|
end
|
38
43
|
end
|
39
44
|
|
40
45
|
def ==(other)
|
41
|
-
other.is_a?(Intersection) &&
|
42
|
-
other.types == types
|
46
|
+
other.is_a?(Intersection) && other.types == types
|
43
47
|
end
|
44
48
|
|
45
49
|
def hash
|
46
|
-
self.class.hash ^ types.hash
|
50
|
+
@hash ||= self.class.hash ^ types.hash
|
47
51
|
end
|
48
52
|
|
49
53
|
alias eql? ==
|
50
54
|
|
51
55
|
def subst(s)
|
52
|
-
self.class.build(location: location,
|
53
|
-
types: types.map {|ty| ty.subst(s) })
|
56
|
+
self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
|
54
57
|
end
|
55
58
|
|
56
59
|
def to_s
|
57
|
-
"(#{types.map(&:to_s).
|
60
|
+
"(#{types.map(&:to_s).join(" & ")})"
|
58
61
|
end
|
59
62
|
|
60
|
-
def free_variables
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
def free_variables()
|
64
|
+
@fvs ||= begin
|
65
|
+
set = Set.new
|
66
|
+
types.each do |type|
|
67
|
+
set.merge(type.free_variables)
|
68
|
+
end
|
69
|
+
set
|
70
|
+
end
|
64
71
|
end
|
65
72
|
|
66
73
|
include Helper::ChildrenLevel
|
data/lib/steep/ast/types/name.rb
CHANGED
@@ -11,9 +11,7 @@ module Steep
|
|
11
11
|
@name = name
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
Set.new
|
16
|
-
end
|
14
|
+
include Helper::NoFreeVariables
|
17
15
|
|
18
16
|
def subst(s)
|
19
17
|
self
|
@@ -41,7 +39,7 @@ module Steep
|
|
41
39
|
alias eql? ==
|
42
40
|
|
43
41
|
def hash
|
44
|
-
self.class.hash ^ name.hash ^ args.hash
|
42
|
+
@hash ||= self.class.hash ^ name.hash ^ args.hash
|
45
43
|
end
|
46
44
|
|
47
45
|
def to_s
|
@@ -57,14 +55,20 @@ module Steep
|
|
57
55
|
end
|
58
56
|
|
59
57
|
def subst(s)
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
if free_variables.intersect?(s.domain)
|
59
|
+
self.class.new(location: location,
|
60
|
+
name: name,
|
61
|
+
args: args.map {|a| a.subst(s) })
|
62
|
+
else
|
63
|
+
self
|
64
|
+
end
|
63
65
|
end
|
64
66
|
|
65
67
|
def free_variables
|
66
|
-
|
67
|
-
|
68
|
+
@fvs ||= Set.new().tap do |set|
|
69
|
+
args.each do |type|
|
70
|
+
set.merge(type.free_variables)
|
71
|
+
end
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
@@ -75,59 +79,7 @@ module Steep
|
|
75
79
|
end
|
76
80
|
end
|
77
81
|
|
78
|
-
class
|
79
|
-
attr_reader :constructor
|
80
|
-
|
81
|
-
def initialize(name:, constructor:, location: nil)
|
82
|
-
raise "Name should be a module name: #{name.inspect}" unless name.is_a?(Names::Module)
|
83
|
-
super(name: name, location: location)
|
84
|
-
@constructor = constructor
|
85
|
-
end
|
86
|
-
|
87
|
-
def ==(other)
|
88
|
-
other.class == self.class &&
|
89
|
-
other.name == name &&
|
90
|
-
other.constructor == constructor
|
91
|
-
end
|
92
|
-
|
93
|
-
alias eql? ==
|
94
|
-
|
95
|
-
def hash
|
96
|
-
self.class.hash ^ name.hash ^ constructor.hash
|
97
|
-
end
|
98
|
-
|
99
|
-
def to_s
|
100
|
-
k = case constructor
|
101
|
-
when true
|
102
|
-
" constructor"
|
103
|
-
when false
|
104
|
-
" noconstructor"
|
105
|
-
when nil
|
106
|
-
""
|
107
|
-
end
|
108
|
-
"singleton(#{name.to_s})"
|
109
|
-
end
|
110
|
-
|
111
|
-
def with_location(new_location)
|
112
|
-
self.class.new(name: name, constructor: constructor, location: new_location)
|
113
|
-
end
|
114
|
-
|
115
|
-
def to_instance(*args)
|
116
|
-
Instance.new(name: name, args: args)
|
117
|
-
end
|
118
|
-
|
119
|
-
NOTHING = ::Object.new
|
120
|
-
|
121
|
-
def updated(constructor: NOTHING)
|
122
|
-
if NOTHING == constructor
|
123
|
-
constructor = self.constructor
|
124
|
-
end
|
125
|
-
|
126
|
-
self.class.new(name: name, constructor: constructor, location: location)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
class Module < Base
|
82
|
+
class Singleton < Base
|
131
83
|
def ==(other)
|
132
84
|
other.class == self.class &&
|
133
85
|
other.name == name
|
@@ -149,12 +101,8 @@ module Steep
|
|
149
101
|
end
|
150
102
|
|
151
103
|
class Instance < Applying
|
152
|
-
def to_class(constructor:)
|
153
|
-
Class.new(name: name, location: location, constructor: constructor)
|
154
|
-
end
|
155
|
-
|
156
104
|
def to_module
|
157
|
-
|
105
|
+
Singleton.new(name: name, location: location)
|
158
106
|
end
|
159
107
|
end
|
160
108
|
|
data/lib/steep/ast/types/nil.rb
CHANGED
data/lib/steep/ast/types/proc.rb
CHANGED
@@ -36,8 +36,11 @@ module Steep
|
|
36
36
|
"^#{params} -> #{return_type}"
|
37
37
|
end
|
38
38
|
|
39
|
-
def free_variables
|
40
|
-
|
39
|
+
def free_variables()
|
40
|
+
@fvs ||= Set.new.tap do |set|
|
41
|
+
set.merge(params.free_variables)
|
42
|
+
set.merge(return_type.free_variables)
|
43
|
+
end
|
41
44
|
end
|
42
45
|
|
43
46
|
def level
|
@@ -26,12 +26,17 @@ module Steep
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def to_s
|
29
|
-
|
29
|
+
strings = elements.keys.sort.map do |key|
|
30
|
+
"#{key.inspect} => #{elements[key]}"
|
31
|
+
end
|
32
|
+
"{ #{strings.join(", ")} }"
|
30
33
|
end
|
31
34
|
|
32
|
-
def free_variables
|
33
|
-
|
34
|
-
|
35
|
+
def free_variables()
|
36
|
+
@fvs ||= Set.new.tap do |set|
|
37
|
+
elements.each_value do |type|
|
38
|
+
set.merge(type.free_variables)
|
39
|
+
end
|
35
40
|
end
|
36
41
|
end
|
37
42
|
|
data/lib/steep/ast/types/self.rb
CHANGED
data/lib/steep/ast/types/top.rb
CHANGED
@@ -30,9 +30,11 @@ module Steep
|
|
30
30
|
"[#{types.join(", ")}]"
|
31
31
|
end
|
32
32
|
|
33
|
-
def free_variables
|
34
|
-
|
35
|
-
|
33
|
+
def free_variables()
|
34
|
+
@fvs ||= Set.new.tap do |set|
|
35
|
+
types.each do |type|
|
36
|
+
set.merge(type.free_variables)
|
37
|
+
end
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
@@ -11,6 +11,9 @@ module Steep
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.build(types:, location: nil)
|
14
|
+
return AST::Types::Bot.new if types.empty?
|
15
|
+
return types.first if types.size == 1
|
16
|
+
|
14
17
|
types.flat_map do |type|
|
15
18
|
if type.is_a?(Union)
|
16
19
|
type.types
|
@@ -29,37 +32,41 @@ module Steep
|
|
29
32
|
type
|
30
33
|
end
|
31
34
|
end.compact.uniq.yield_self do |tys|
|
32
|
-
|
35
|
+
case tys.size
|
36
|
+
when 0
|
37
|
+
AST::Types::Bot.new
|
38
|
+
when 1
|
33
39
|
tys.first
|
34
40
|
else
|
35
|
-
new(types: tys
|
41
|
+
new(types: tys, location: location)
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
39
45
|
|
40
46
|
def ==(other)
|
41
47
|
other.is_a?(Union) &&
|
42
|
-
other.types == types
|
48
|
+
Set.new(other.types) == Set.new(types)
|
43
49
|
end
|
44
50
|
|
45
51
|
def hash
|
46
|
-
self.class.hash ^ types.hash
|
52
|
+
@hash ||= self.class.hash ^ types.sort_by(&:to_s).hash
|
47
53
|
end
|
48
54
|
|
49
55
|
alias eql? ==
|
50
56
|
|
51
57
|
def subst(s)
|
52
|
-
self.class.build(location: location,
|
53
|
-
types: types.map {|ty| ty.subst(s) })
|
58
|
+
self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
|
54
59
|
end
|
55
60
|
|
56
61
|
def to_s
|
57
|
-
"(#{types.map(&:to_s).
|
62
|
+
"(#{types.map(&:to_s).join(" | ")})"
|
58
63
|
end
|
59
64
|
|
60
65
|
def free_variables
|
61
|
-
|
62
|
-
|
66
|
+
@fvs ||= Set.new.tap do |set|
|
67
|
+
types.each do |type|
|
68
|
+
set.merge(type.free_variables)
|
69
|
+
end
|
63
70
|
end
|
64
71
|
end
|
65
72
|
|
data/lib/steep/ast/types/var.rb
CHANGED
data/lib/steep/ast/types/void.rb
CHANGED
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
|
|