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
@@ -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
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
module Logic
|
5
|
+
class Base
|
6
|
+
attr_reader :location
|
7
|
+
|
8
|
+
def subst(s)
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def free_variables
|
13
|
+
@fvs ||= Set[]
|
14
|
+
end
|
15
|
+
|
16
|
+
def hash
|
17
|
+
self.class.hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
other.class ==self.class
|
22
|
+
end
|
23
|
+
|
24
|
+
alias eql? ==
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
"<% #{self.class} %>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Not < Base
|
32
|
+
def initialize(location: nil)
|
33
|
+
@location = location
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ReceiverIsNil < Base
|
38
|
+
def initialize(location: nil)
|
39
|
+
@location = location
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ReceiverIsNotNil < Base
|
44
|
+
def initialize(location: nil)
|
45
|
+
@location = location
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class ReceiverIsArg < Base
|
50
|
+
def initialize(location: nil)
|
51
|
+
@location = location
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class ArgIsReceiver < Base
|
56
|
+
def initialize(location: nil)
|
57
|
+
@location = location
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
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