steep 1.1.1 → 1.2.0.pre.1
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 +20 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +12 -11
- data/Gemfile.steep +1 -1
- data/Gemfile.steep.lock +9 -9
- data/README.md +3 -3
- data/Steepfile +23 -0
- data/bin/steep-prof +2 -1
- data/lib/steep/annotation_parser.rb +1 -1
- data/lib/steep/ast/types/class.rb +4 -0
- data/lib/steep/ast/types/factory.rb +86 -602
- data/lib/steep/ast/types/instance.rb +4 -0
- data/lib/steep/ast/types/literal.rb +1 -1
- data/lib/steep/ast/types/proc.rb +22 -8
- data/lib/steep/ast/types/self.rb +4 -0
- data/lib/steep/ast/types/union.rb +1 -1
- data/lib/steep/cli.rb +24 -1
- data/lib/steep/diagnostic/ruby.rb +17 -22
- data/lib/steep/drivers/checkfile.rb +205 -0
- data/lib/steep/drivers/validate.rb +3 -1
- data/lib/steep/equatable.rb +2 -0
- data/lib/steep/interface/block.rb +21 -11
- data/lib/steep/interface/builder.rb +756 -0
- data/lib/steep/interface/function.rb +32 -24
- data/lib/steep/interface/method_type.rb +191 -78
- data/lib/steep/interface/shape.rb +132 -0
- data/lib/steep/interface/substitution.rb +23 -12
- data/lib/steep/interface/type_param.rb +1 -2
- data/lib/steep/path_helper.rb +1 -1
- data/lib/steep/project.rb +5 -7
- data/lib/steep/server/base_worker.rb +2 -2
- data/lib/steep/server/change_buffer.rb +4 -3
- data/lib/steep/server/interaction_worker.rb +1 -1
- data/lib/steep/server/master.rb +69 -9
- data/lib/steep/server/type_check_worker.rb +13 -11
- data/lib/steep/server/worker_process.rb +9 -7
- data/lib/steep/services/completion_provider.rb +15 -3
- data/lib/steep/services/hover_provider/singleton_methods.rb +5 -6
- data/lib/steep/services/signature_service.rb +13 -8
- data/lib/steep/services/type_check_service.rb +2 -0
- data/lib/steep/signature/validator.rb +1 -1
- data/lib/steep/subtyping/check.rb +154 -103
- data/lib/steep/subtyping/relation.rb +3 -3
- data/lib/steep/subtyping/result.rb +20 -2
- data/lib/steep/subtyping/variable_variance.rb +9 -0
- data/lib/steep/type_construction.rb +558 -299
- data/lib/steep/type_inference/block_params.rb +169 -86
- data/lib/steep/type_inference/logic_type_interpreter.rb +9 -14
- data/lib/steep/type_inference/method_params.rb +12 -7
- data/lib/steep/type_inference/send_args.rb +41 -35
- data/lib/steep/type_inference/type_env_builder.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +71 -2
- data/rbs_collection.steep.lock.yaml +18 -30
- data/rbs_collection.steep.yaml +1 -0
- data/sig/shims/language-server_protocol.rbs +20 -0
- data/sig/shims/tagged_logging.rbs +6 -0
- data/sig/steep/ast/annotation/collection.rbs +6 -6
- data/sig/steep/ast/types/class.rbs +3 -0
- data/sig/steep/ast/types/factory.rbs +38 -32
- data/sig/steep/ast/types/instance.rbs +3 -0
- data/sig/steep/ast/types/intersection.rbs +1 -1
- data/sig/steep/ast/types/literal.rbs +7 -7
- data/sig/steep/ast/types/name.rbs +14 -13
- data/sig/steep/ast/types/proc.rbs +3 -1
- data/sig/steep/ast/types/self.rbs +3 -0
- data/sig/steep/ast/types/var.rbs +1 -1
- data/sig/steep/diagnostic/ruby.rbs +30 -34
- data/sig/steep/drivers/annotations.rbs +17 -0
- data/sig/steep/drivers/check.rbs +33 -0
- data/sig/steep/drivers/checkfile.rbs +26 -0
- data/sig/steep/drivers/diagnostic_printer.rbs +25 -0
- data/sig/steep/drivers/init.rbs +19 -0
- data/sig/steep/drivers/langserver.rbs +35 -0
- data/sig/steep/drivers/print_project.rbs +15 -0
- data/sig/steep/drivers/stats.rbs +37 -0
- data/sig/steep/drivers/utils/driver_helper.rbs +23 -0
- data/sig/steep/drivers/utils/jobs_count.rbs +11 -0
- data/sig/steep/drivers/validate.rbs +15 -0
- data/sig/steep/drivers/vendor.rbs +19 -0
- data/sig/steep/drivers/watch.rbs +27 -0
- data/sig/steep/drivers/worker.rbs +31 -0
- data/sig/steep/equatable.rbs +11 -0
- data/sig/steep/index/rbs_index.rbs +91 -0
- data/sig/steep/index/signature_symbol_provider.rbs +29 -0
- data/sig/steep/index/source_index.rbs +63 -0
- data/sig/steep/interface/block.rbs +3 -1
- data/sig/steep/interface/builder.rbs +152 -0
- data/sig/steep/interface/function.rbs +67 -55
- data/sig/steep/interface/method_type.rbs +60 -12
- data/sig/steep/interface/shape.rbs +61 -0
- data/sig/steep/interface/substitution.rbs +18 -22
- data/sig/steep/interface/type_param.rbs +9 -1
- data/sig/steep/path_helper.rbs +7 -0
- data/sig/steep/project/pattern.rbs +10 -10
- data/sig/steep/project/target.rbs +2 -2
- data/sig/steep/project.rbs +15 -8
- data/sig/steep/server/base_worker.rbs +49 -0
- data/sig/steep/server/change_buffer.rbs +32 -0
- data/sig/steep/server/interaction_worker.rbs +41 -0
- data/sig/steep/server/lsp_formatter.rbs +29 -0
- data/sig/steep/server/master.rbs +260 -0
- data/sig/steep/server/type_check_worker.rbs +135 -0
- data/sig/steep/server/worker_process.rbs +29 -0
- data/sig/steep/services/completion_provider.rbs +5 -5
- data/sig/steep/services/content_change.rbs +14 -12
- data/sig/steep/services/file_loader.rbs +12 -4
- data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
- data/sig/steep/services/path_assignment.rbs +7 -7
- data/sig/steep/services/signature_service.rbs +67 -40
- data/sig/steep/services/type_check_service.rbs +53 -39
- data/sig/steep/subtyping/check.rbs +80 -44
- data/sig/steep/subtyping/relation.rbs +24 -22
- data/sig/steep/subtyping/result.rbs +48 -30
- data/sig/steep/subtyping/variable_variance.rbs +2 -0
- data/sig/steep/type_construction.rbs +132 -23
- data/sig/steep/type_inference/block_params.rbs +120 -18
- data/sig/steep/type_inference/context.rbs +45 -20
- data/sig/steep/type_inference/context_array.rbs +37 -0
- data/sig/steep/type_inference/logic_type_interpreter.rbs +3 -1
- data/sig/steep/type_inference/method_params.rbs +13 -9
- data/sig/steep/type_inference/send_args.rbs +229 -0
- data/sig/steep/type_inference/type_env_builder.rbs +1 -1
- data/sig/steep/typing.rbs +4 -4
- data/sig/steep.rbs +4 -2
- data/smoke/block/e.rb +12 -0
- data/smoke/block/e.rbs +4 -0
- data/smoke/block/test_expectations.yml +12 -0
- data/smoke/regression/block_param_split.rb +7 -0
- data/smoke/regression/block_param_split.rbs +3 -0
- data/smoke/regression/empty_yield.rb +5 -0
- data/smoke/regression/empty_yield.rbs +3 -0
- data/smoke/regression/test_expectations.yml +12 -0
- data/smoke/yield/test_expectations.yml +4 -4
- data/steep.gemspec +2 -1
- metadata +61 -9
- data/lib/steep/interface/interface.rb +0 -34
- data/sig/steep/interface/interface.rbs +0 -23
- data/sig/version.rbs +0 -3
@@ -37,7 +37,7 @@ module Steep
|
|
37
37
|
if ty == type
|
38
38
|
self
|
39
39
|
else
|
40
|
-
self.class.new(ty)
|
40
|
+
_ = self.class.new(ty)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -47,7 +47,7 @@ module Steep
|
|
47
47
|
|
48
48
|
def map_type(&block)
|
49
49
|
if block_given?
|
50
|
-
self.class.new(yield type)
|
50
|
+
_ = self.class.new(yield type)
|
51
51
|
else
|
52
52
|
enum_for(:map_type)
|
53
53
|
end
|
@@ -94,7 +94,7 @@ module Steep
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def map_type(&block)
|
97
|
-
if
|
97
|
+
if block
|
98
98
|
map {|param| param.map_type(&block) }
|
99
99
|
else
|
100
100
|
enum_for :map_type
|
@@ -123,7 +123,7 @@ module Steep
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def each(&block)
|
126
|
-
if
|
126
|
+
if block
|
127
127
|
yield head
|
128
128
|
tail&.each(&block)
|
129
129
|
else
|
@@ -411,11 +411,11 @@ module Steep
|
|
411
411
|
end
|
412
412
|
|
413
413
|
def each(&block)
|
414
|
-
if
|
414
|
+
if block
|
415
415
|
requireds.each(&block)
|
416
416
|
optionals.each(&block)
|
417
417
|
if rest
|
418
|
-
yield nil, rest
|
418
|
+
yield [nil, rest]
|
419
419
|
end
|
420
420
|
else
|
421
421
|
enum_for :each
|
@@ -433,7 +433,7 @@ module Steep
|
|
433
433
|
end
|
434
434
|
|
435
435
|
def map_type(&block)
|
436
|
-
if
|
436
|
+
if block
|
437
437
|
rs = requireds.transform_values(&block)
|
438
438
|
os = optionals.transform_values(&block)
|
439
439
|
r = rest&.yield_self(&block)
|
@@ -819,7 +819,7 @@ module Steep
|
|
819
819
|
end
|
820
820
|
|
821
821
|
def each_type(&block)
|
822
|
-
if
|
822
|
+
if block
|
823
823
|
positional_params&.each_type(&block)
|
824
824
|
keyword_params.each_type(&block)
|
825
825
|
else
|
@@ -842,16 +842,19 @@ module Steep
|
|
842
842
|
def subst(s)
|
843
843
|
return self if s.empty?
|
844
844
|
return self if empty?
|
845
|
-
return self if
|
845
|
+
return self if each_type.none? {|t| s.apply?(t) }
|
846
846
|
|
847
|
-
pp = positional_params
|
848
|
-
kp = keyword_params
|
847
|
+
pp = positional_params
|
848
|
+
kp = keyword_params
|
849
849
|
|
850
|
-
if positional_params
|
851
|
-
|
852
|
-
else
|
853
|
-
self.class.new(positional_params: pp, keyword_params: kp)
|
850
|
+
if positional_params && positional_params.each_type.any? {|t| s.apply?(t) }
|
851
|
+
pp = positional_params.subst(s)
|
854
852
|
end
|
853
|
+
if keyword_params && keyword_params.each_type.any? {|t| s.apply?(t) }
|
854
|
+
kp = keyword_params.subst(s)
|
855
|
+
end
|
856
|
+
|
857
|
+
self.class.new(positional_params: pp, keyword_params: kp)
|
855
858
|
end
|
856
859
|
|
857
860
|
def size
|
@@ -950,19 +953,22 @@ module Steep
|
|
950
953
|
def subst(s)
|
951
954
|
return self if s.empty?
|
952
955
|
|
953
|
-
|
954
|
-
|
955
|
-
return_type: return_type.subst(s),
|
956
|
-
location: location
|
957
|
-
)
|
958
|
-
end
|
956
|
+
ps = params.subst(s)
|
957
|
+
ret = return_type.subst(s)
|
959
958
|
|
960
|
-
|
961
|
-
|
959
|
+
if ps == params && ret == return_type
|
960
|
+
self
|
961
|
+
else
|
962
|
+
Function.new(
|
963
|
+
params: ps,
|
964
|
+
return_type: ret,
|
965
|
+
location: location
|
966
|
+
)
|
967
|
+
end
|
962
968
|
end
|
963
969
|
|
964
970
|
def each_type(&block)
|
965
|
-
if
|
971
|
+
if block
|
966
972
|
params.each_type(&block)
|
967
973
|
yield return_type
|
968
974
|
else
|
@@ -970,6 +976,8 @@ module Steep
|
|
970
976
|
end
|
971
977
|
end
|
972
978
|
|
979
|
+
alias each_child each_type
|
980
|
+
|
973
981
|
def map_type(&block)
|
974
982
|
Function.new(
|
975
983
|
params: params.map_type(&block),
|
@@ -32,30 +32,37 @@ module Steep
|
|
32
32
|
if block
|
33
33
|
set.merge(block.free_variables)
|
34
34
|
end
|
35
|
-
set.subtract(type_params)
|
35
|
+
set.subtract(type_params.map(&:name))
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
def subst(s)
|
40
40
|
return self if s.empty?
|
41
|
-
return self if
|
41
|
+
return self if each_type.none? {|t| s.apply?(t) }
|
42
42
|
|
43
|
-
|
43
|
+
if type_params.any? {|param| s.key?(param.name) }
|
44
|
+
s_ = s.except(type_params.map(&:name))
|
45
|
+
else
|
46
|
+
s_ = s
|
47
|
+
end
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
ty = type.subst(s_)
|
50
|
+
bl = block&.subst(s_)
|
51
|
+
|
52
|
+
if ty == type && bl == block
|
53
|
+
self
|
54
|
+
else
|
55
|
+
self.class.new(type_params: type_params, type: ty, block: bl, method_decls: method_decls)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
|
53
59
|
def each_type(&block)
|
54
|
-
if
|
60
|
+
if block
|
55
61
|
type.each_type(&block)
|
56
|
-
|
57
|
-
|
58
|
-
|
62
|
+
if block()
|
63
|
+
yield(block().self_type) if block().self_type
|
64
|
+
block().type.params.each_type(&block)
|
65
|
+
yield(block().type.return_type)
|
59
66
|
end
|
60
67
|
else
|
61
68
|
enum_for :each_type
|
@@ -99,14 +106,15 @@ module Steep
|
|
99
106
|
type_params_2, s2 = TypeParam.rename(other.type_params)
|
100
107
|
type_params = type_params_1 + type_params_2
|
101
108
|
|
102
|
-
block =
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
109
|
+
block =
|
110
|
+
case
|
111
|
+
when (b = self.block) && (ob = other.block)
|
112
|
+
b.subst(s1) + ob.subst(s2)
|
113
|
+
when b = self.block
|
114
|
+
b.to_optional.subst(s1)
|
115
|
+
when ob = other.block
|
116
|
+
ob.to_optional.subst(s2)
|
117
|
+
end
|
110
118
|
|
111
119
|
self.class.new(
|
112
120
|
type_params: type_params,
|
@@ -126,82 +134,187 @@ module Steep
|
|
126
134
|
unify_overload(other)
|
127
135
|
end
|
128
136
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
+
def equals_modulo_type_params?(other)
|
138
|
+
case
|
139
|
+
when self.type_params.empty? && other.type_params.empty?
|
140
|
+
self == other
|
141
|
+
when self.type_params.size == other.type_params.size
|
142
|
+
new_names = self.type_params.map(&:name)
|
143
|
+
|
144
|
+
self_params, self_subst = TypeParam.rename(self.type_params, self.type_params.map(&:name), new_names)
|
145
|
+
other_params, other_subst = TypeParam.rename(other.type_params, other.type_params.map(&:name), new_names)
|
146
|
+
|
147
|
+
self_params == other_params && self.instantiate(self_subst) == other.instantiate(other_subst)
|
137
148
|
else
|
138
|
-
|
139
|
-
other = other.instantiate(s2)
|
140
|
-
type_params = self.type_params + other_params
|
149
|
+
false
|
141
150
|
end
|
151
|
+
end
|
142
152
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
153
|
+
def self.union(type1, type2, check)
|
154
|
+
try_type_params(
|
155
|
+
type1,
|
156
|
+
type2,
|
157
|
+
check,
|
158
|
+
-> (t1, t2) { t1 | t2 },
|
159
|
+
-> (original, generated) { Subtyping::Relation.new(sub_type: original, super_type: generated) }
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.intersection(type1, type2, check)
|
164
|
+
try_type_params(
|
165
|
+
type1,
|
166
|
+
type2,
|
167
|
+
check,
|
168
|
+
-> (t1, t2) { t1 & t2 },
|
169
|
+
-> (original, generated) { Subtyping::Relation.new(sub_type: generated, super_type: original) }
|
170
|
+
)
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.try_type_params(type1, type2, check, generate, relation)
|
174
|
+
return type1 if type1.equals_modulo_type_params?(type2)
|
175
|
+
|
176
|
+
case
|
177
|
+
when type1.type_params.empty? && type2.type_params.empty?
|
178
|
+
generate[type1, type2]
|
179
|
+
when type1.type_params.empty?
|
180
|
+
if mt = generate[type1, type2.with(type_params: [])]
|
181
|
+
mt.with(type_params: type2.type_params)
|
182
|
+
end
|
183
|
+
when type2.type_params.empty?
|
184
|
+
if mt = generate[type1.with(type_params: []), type2]
|
185
|
+
mt.with(type_params: type1.type_params)
|
186
|
+
end
|
187
|
+
when type1.type_params.size == type2.type_params.size
|
188
|
+
params1, s1 = TypeParam.rename(type1.type_params)
|
189
|
+
params2, s2 = TypeParam.rename(type2.type_params)
|
190
|
+
|
191
|
+
type1_ = type1.instantiate(s1)
|
192
|
+
type2_ = type2.instantiate(s2)
|
193
|
+
if mt = generate[type1_, type2_]
|
194
|
+
check.push_variable_bounds(params1 + params2) do
|
195
|
+
variables = type1.type_params.map(&:name) + type2.type_params.map(&:name)
|
196
|
+
constraints = Subtyping::Constraints.new(unknowns: variables)
|
197
|
+
|
198
|
+
check.with_context(self_type: AST::Builtin.any_type, instance_type: AST::Builtin.any_type, class_type: AST::Builtin.any_type, constraints: constraints) do
|
199
|
+
result1 = check.check_method_type(:__method_on_type1, relation[type1.with(type_params: []), mt])
|
200
|
+
result2 = check.check_method_type(:__method_on_type2, relation[type2.with(type_params: []), mt])
|
201
|
+
|
202
|
+
if result1.success? && result2.success?
|
203
|
+
unless type1.type_params.map(&:name).zip(type2.type_params.map(&:name)).all? {|pair|
|
204
|
+
constraints.upper_bound(pair[0]) == constraints.upper_bound(pair[1] || raise) &&
|
205
|
+
constraints.lower_bound(pair[0]) == constraints.lower_bound(pair[1] || raise)
|
206
|
+
}
|
207
|
+
return
|
208
|
+
end
|
209
|
+
|
210
|
+
params2_, s2_ = TypeParam.rename(type2.type_params, type2.type_params.map(&:name), type1.type_params.map(&:name))
|
211
|
+
if mt_ = generate[type1.with(type_params: []), type2.instantiate(s2_)]
|
212
|
+
mt_.with(
|
213
|
+
type_params: type1.type_params.map.with_index {|param1, index|
|
214
|
+
param2 = params2_[index] or raise
|
215
|
+
ub1 = param1.upper_bound
|
216
|
+
ub2 = param2.upper_bound
|
217
|
+
|
218
|
+
case
|
219
|
+
when ub1 && ub2
|
220
|
+
param1.update(upper_bound: AST::Types::Union.build(types: [ub1, ub2]))
|
221
|
+
when ub2
|
222
|
+
param1.update(upper_bound: ub2)
|
223
|
+
else
|
224
|
+
param1
|
225
|
+
end
|
226
|
+
}
|
227
|
+
)
|
228
|
+
end
|
161
229
|
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def |(other)
|
237
|
+
return self if other == self
|
238
|
+
|
239
|
+
params = self.type.params & other.type.params or return
|
240
|
+
block =
|
241
|
+
case
|
242
|
+
when (b = block()) && (ob = other.block)
|
243
|
+
self_type =
|
244
|
+
case
|
245
|
+
when (self_self = b.self_type) && (other_self = ob.self_type)
|
246
|
+
AST::Types::Union.build(types: [self_self, other_self])
|
247
|
+
when b.self_type || ob.self_type
|
248
|
+
AST::Types::Bot.new()
|
249
|
+
else
|
250
|
+
nil
|
251
|
+
end
|
252
|
+
|
253
|
+
# Return when the two block parameters are imcompatible.
|
254
|
+
return unless b.type.params & ob.type.params
|
255
|
+
|
256
|
+
block_params = b.type.params | ob.type.params or return
|
257
|
+
|
258
|
+
block_return_type = AST::Types::Intersection.build(types: [b.type.return_type, ob.type.return_type])
|
259
|
+
block_type = Function.new(params: block_params, return_type: block_return_type, location: nil)
|
260
|
+
|
261
|
+
Block.new(
|
262
|
+
type: block_type,
|
263
|
+
optional: b.optional && ob.optional,
|
264
|
+
self_type: self_type
|
265
|
+
)
|
266
|
+
when (b = block()) && b.optional?
|
267
|
+
b
|
268
|
+
when other.block && other.block.optional?
|
269
|
+
other.block
|
270
|
+
when !self.block && !other.block
|
271
|
+
nil
|
272
|
+
else
|
273
|
+
return
|
274
|
+
end
|
162
275
|
return_type = AST::Types::Union.build(types: [self.type.return_type, other.type.return_type])
|
163
276
|
|
164
277
|
MethodType.new(
|
165
|
-
type_params:
|
278
|
+
type_params: [],
|
166
279
|
type: Function.new(params: params, return_type: return_type, location: nil),
|
167
280
|
block: block,
|
168
281
|
method_decls: method_decls + other.method_decls
|
169
282
|
)
|
170
283
|
end
|
171
284
|
|
172
|
-
# Returns a method type which is a sub-type of both self and other.
|
173
|
-
# (self & other) <: self && (self & other) <: other
|
174
|
-
#
|
175
|
-
# Returns nil if self and other are incompatible.
|
176
|
-
#
|
177
285
|
def &(other)
|
178
|
-
if other
|
179
|
-
type_params = self.type_params
|
180
|
-
else
|
181
|
-
other_params, s2 = TypeParam.rename(other.type_params)
|
182
|
-
other = other.instantiate(s2)
|
183
|
-
type_params = self.type_params + other_params
|
184
|
-
end
|
286
|
+
return self if self == other
|
185
287
|
|
186
|
-
params = self.type.params | other.type.params
|
187
|
-
block =
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
288
|
+
params = self.type.params | other.type.params or return
|
289
|
+
block =
|
290
|
+
case
|
291
|
+
when (b = self.block) && (ob = other.block)
|
292
|
+
self_type =
|
293
|
+
case
|
294
|
+
when (self_self = b.self_type) && (other_self = ob.self_type)
|
295
|
+
AST::Types::Intersection.build(types: [self_self, other_self])
|
296
|
+
when b.self_type || ob.self_type
|
297
|
+
AST::Types::Top.new()
|
298
|
+
else
|
299
|
+
nil
|
300
|
+
end
|
301
|
+
|
302
|
+
block_params = b.type.params & ob.type.params or return
|
303
|
+
block_return_type = AST::Types::Union.build(types: [b.type.return_type, ob.type.return_type])
|
304
|
+
block_type = Function.new(params: block_params, return_type: block_return_type, location: nil)
|
305
|
+
Block.new(
|
306
|
+
type: block_type,
|
307
|
+
optional: b.optional || ob.optional,
|
308
|
+
self_type: self_type
|
309
|
+
)
|
310
|
+
else
|
311
|
+
self.block || other.block
|
312
|
+
end
|
200
313
|
|
201
314
|
return_type = AST::Types::Intersection.build(types: [self.type.return_type, other.type.return_type])
|
202
315
|
|
203
316
|
MethodType.new(
|
204
|
-
type_params:
|
317
|
+
type_params: [],
|
205
318
|
type: Function.new(params: params, return_type: return_type, location: nil),
|
206
319
|
block: block,
|
207
320
|
method_decls: method_decls + other.method_decls
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Steep
|
2
|
+
module Interface
|
3
|
+
class Shape
|
4
|
+
class Entry
|
5
|
+
attr_reader :method_types
|
6
|
+
|
7
|
+
def initialize(method_types:)
|
8
|
+
@method_types = method_types
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"{ #{method_types.join(" || ")} }"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Methods
|
17
|
+
attr_reader :substs, :methods, :resolved_methods
|
18
|
+
|
19
|
+
include Enumerable
|
20
|
+
|
21
|
+
def initialize(substs:, methods:)
|
22
|
+
@substs = substs
|
23
|
+
@methods = methods
|
24
|
+
@resolved_methods = methods.transform_values { nil }
|
25
|
+
end
|
26
|
+
|
27
|
+
def key?(name)
|
28
|
+
methods.key?(name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def []=(name, entry)
|
32
|
+
resolved_methods[name] = nil
|
33
|
+
methods[name] = entry
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](name)
|
37
|
+
return nil unless key?(name)
|
38
|
+
|
39
|
+
resolved_methods[name] ||= begin
|
40
|
+
Entry.new(
|
41
|
+
method_types: methods[name].method_types.map do |method_type|
|
42
|
+
method_type.subst(subst)
|
43
|
+
end
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def each(&block)
|
49
|
+
if block
|
50
|
+
methods.each_key do |name|
|
51
|
+
entry = self[name] or raise
|
52
|
+
yield [name, entry]
|
53
|
+
end
|
54
|
+
else
|
55
|
+
enum_for :each
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def each_name(&block)
|
60
|
+
if block
|
61
|
+
methods.each_key(&block)
|
62
|
+
else
|
63
|
+
enum_for :each_name
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def subst
|
68
|
+
@subst ||= begin
|
69
|
+
substs.each_with_object(Substitution.empty) do |s, ss|
|
70
|
+
ss.merge!(s, overwrite: true)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def push_substitution(subst)
|
76
|
+
Methods.new(substs: [*substs, subst], methods: methods)
|
77
|
+
end
|
78
|
+
|
79
|
+
def merge!(other)
|
80
|
+
other.each do |name, entry|
|
81
|
+
methods[name] = entry
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def +(other)
|
86
|
+
methods = Methods.new(substs: [], methods: {})
|
87
|
+
|
88
|
+
methods.merge!(self)
|
89
|
+
methods.merge!(other)
|
90
|
+
|
91
|
+
methods
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
attr_reader :type
|
96
|
+
attr_reader :methods
|
97
|
+
|
98
|
+
def initialize(type:, private:, methods: nil)
|
99
|
+
@type = type
|
100
|
+
@private = private
|
101
|
+
@methods = methods || Methods.new(substs: [], methods: {})
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
"#<#{self.class.name}: type=#{type}, private?=#{@private}, methods={#{methods.each_name.sort.join(", ")}}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def update(type: self.type, methods: self.methods)
|
109
|
+
_ = self.class.new(type: type, private: private?, methods: methods)
|
110
|
+
end
|
111
|
+
|
112
|
+
def subst(s, type: nil)
|
113
|
+
ty =
|
114
|
+
if type
|
115
|
+
type
|
116
|
+
else
|
117
|
+
self.type.subst(s)
|
118
|
+
end
|
119
|
+
|
120
|
+
Shape.new(type: ty, private: private?, methods: methods.push_substitution(s))
|
121
|
+
end
|
122
|
+
|
123
|
+
def private?
|
124
|
+
@private
|
125
|
+
end
|
126
|
+
|
127
|
+
def public?
|
128
|
+
!private?
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -27,9 +27,9 @@ module Steep
|
|
27
27
|
|
28
28
|
def self.empty
|
29
29
|
new(dictionary: {},
|
30
|
-
instance_type:
|
31
|
-
module_type:
|
32
|
-
self_type:
|
30
|
+
instance_type: AST::Types::Instance.instance,
|
31
|
+
module_type: AST::Types::Class.instance,
|
32
|
+
self_type: AST::Types::Self.instance)
|
33
33
|
end
|
34
34
|
|
35
35
|
def empty?
|
@@ -39,17 +39,13 @@ module Steep
|
|
39
39
|
self_type.is_a?(AST::Types::Self)
|
40
40
|
end
|
41
41
|
|
42
|
-
INSTANCE_TYPE = AST::Types::Instance.new
|
43
|
-
CLASS_TYPE = AST::Types::Class.new
|
44
|
-
SELF_TYPE = AST::Types::Self.new
|
45
|
-
|
46
42
|
def domain
|
47
43
|
set = Set.new
|
48
44
|
|
49
45
|
set.merge(dictionary.keys)
|
50
|
-
set <<
|
51
|
-
set <<
|
52
|
-
set <<
|
46
|
+
set << AST::Types::Instance.instance unless instance_type.is_a?(AST::Types::Instance)
|
47
|
+
set << AST::Types::Class.instance unless instance_type.is_a?(AST::Types::Class)
|
48
|
+
set << AST::Types::Instance.instance unless instance_type.is_a?(AST::Types::Self)
|
53
49
|
|
54
50
|
set
|
55
51
|
end
|
@@ -76,7 +72,22 @@ module Steep
|
|
76
72
|
dictionary.key?(var)
|
77
73
|
end
|
78
74
|
|
79
|
-
def
|
75
|
+
def apply?(type)
|
76
|
+
case type
|
77
|
+
when AST::Types::Var
|
78
|
+
key?(type.name)
|
79
|
+
when AST::Types::Self
|
80
|
+
!self_type.is_a?(AST::Types::Self)
|
81
|
+
when AST::Types::Instance
|
82
|
+
!instance_type.is_a?(AST::Types::Instance)
|
83
|
+
when AST::Types::Class
|
84
|
+
!module_type.is_a?(AST::Types::Class)
|
85
|
+
else
|
86
|
+
type.each_child.any? {|t| apply?(t) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.build(vars, types = nil, instance_type: AST::Types::Instance.instance, module_type: AST::Types::Class.instance, self_type: AST::Types::Self.instance)
|
80
91
|
types ||= vars.map {|var| AST::Types::Var.fresh(var) }
|
81
92
|
|
82
93
|
raise InvalidSubstitutionError.new(vars_size: vars.size, types_size: types.size) unless vars.size == types.size
|
@@ -90,7 +101,7 @@ module Steep
|
|
90
101
|
|
91
102
|
def except(vars)
|
92
103
|
self.class.new(
|
93
|
-
dictionary: dictionary,
|
104
|
+
dictionary: dictionary.dup,
|
94
105
|
instance_type: instance_type,
|
95
106
|
module_type: module_type,
|
96
107
|
self_type: self_type
|
@@ -29,9 +29,8 @@ module Steep
|
|
29
29
|
name.hash ^ upper_bound.hash ^ variance.hash ^ unchecked.hash
|
30
30
|
end
|
31
31
|
|
32
|
-
def self.rename(params, conflicting_names = params.map(&:name))
|
32
|
+
def self.rename(params, conflicting_names = params.map(&:name), new_names = conflicting_names.map {|n| AST::Types::Var.fresh_name(n) })
|
33
33
|
unless conflicting_names.empty?
|
34
|
-
new_names = conflicting_names.map {|n| AST::Types::Var.fresh_name(n) }
|
35
34
|
hash = conflicting_names.zip(new_names).to_h
|
36
35
|
new_types = new_names.map {|n| AST::Types::Var.new(name: n) }
|
37
36
|
|
data/lib/steep/path_helper.rb
CHANGED