steep 1.7.0.dev.2 → 1.7.0.dev.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +10 -12
- data/gemfile_steep/Gemfile.lock +8 -10
- data/lib/steep/ast/types/helper.rb +4 -0
- data/lib/steep/ast/types/intersection.rb +7 -0
- data/lib/steep/ast/types/record.rb +7 -0
- data/lib/steep/ast/types/tuple.rb +7 -0
- data/lib/steep/ast/types/union.rb +7 -0
- data/lib/steep/drivers/stats.rb +2 -2
- data/lib/steep/drivers/validate.rb +4 -2
- data/lib/steep/expectations.rb +2 -2
- data/lib/steep/interface/builder.rb +336 -360
- data/lib/steep/interface/function.rb +69 -6
- data/lib/steep/interface/method_type.rb +3 -3
- data/lib/steep/interface/shape.rb +69 -18
- data/lib/steep/interface/substitution.rb +4 -0
- data/lib/steep/node_helper.rb +18 -1
- data/lib/steep/services/completion_provider.rb +19 -17
- data/lib/steep/services/signature_help_provider.rb +6 -9
- data/lib/steep/subtyping/check.rb +4 -16
- data/lib/steep/test.rb +9 -0
- data/lib/steep/type_construction.rb +13 -9
- data/lib/steep/type_inference/block_params.rb +11 -3
- data/lib/steep/type_inference/context.rb +1 -1
- data/lib/steep/type_inference/logic_type_interpreter.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +11 -7
- data/sig/steep/ast/types/helper.rbs +2 -0
- data/sig/steep/ast/types/intersection.rbs +2 -0
- data/sig/steep/ast/types/name.rbs +4 -0
- data/sig/steep/ast/types/record.rbs +2 -0
- data/sig/steep/ast/types/tuple.rbs +2 -0
- data/sig/steep/ast/types/union.rbs +2 -0
- data/sig/steep/expectations.rbs +1 -1
- data/sig/steep/interface/block.rbs +2 -2
- data/sig/steep/interface/builder.rbs +94 -108
- data/sig/steep/interface/function.rbs +34 -29
- data/sig/steep/interface/shape.rbs +23 -4
- data/sig/steep/interface/substitution.rbs +2 -0
- data/sig/steep/node_helper.rbs +11 -0
- data/sig/steep/services/signature_help_provider.rbs +2 -0
- data/sig/steep/subtyping/constraints.rbs +2 -2
- data/sig/steep/type_construction.rbs +1 -1
- data/sig/steep/type_inference/block_params.rbs +2 -2
- data/sig/steep/type_inference/context.rbs +2 -0
- data/sig/steep.rbs +1 -1
- metadata +3 -2
@@ -3,346 +3,305 @@ module Steep
|
|
3
3
|
class Builder
|
4
4
|
class Config
|
5
5
|
attr_reader :self_type, :class_type, :instance_type, :variable_bounds
|
6
|
-
attr_reader :resolve_self, :resolve_instance, :resolve_class
|
7
6
|
|
8
|
-
def initialize(self_type:, class_type
|
7
|
+
def initialize(self_type:, class_type: nil, instance_type: nil, variable_bounds:)
|
9
8
|
@self_type = self_type
|
10
9
|
@class_type = class_type
|
11
10
|
@instance_type = instance_type
|
12
|
-
@resolve_self = resolve_self
|
13
|
-
@resolve_class = resolve_class
|
14
|
-
@resolve_instance = resolve_instance
|
15
11
|
@variable_bounds = variable_bounds
|
16
|
-
end
|
17
|
-
|
18
|
-
def update(self_type: self.self_type, class_type: self.class_type, instance_type: self.instance_type, resolve_self: self.resolve_self, resolve_class: self.resolve_class, resolve_instance: self.resolve_instance, variable_bounds: self.variable_bounds)
|
19
|
-
_ = self.class.new(
|
20
|
-
self_type: self_type,
|
21
|
-
class_type: class_type,
|
22
|
-
instance_type: instance_type,
|
23
|
-
resolve_self: resolve_self,
|
24
|
-
resolve_class: resolve_class,
|
25
|
-
resolve_instance: resolve_instance,
|
26
|
-
variable_bounds: variable_bounds
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
def no_resolve
|
31
|
-
if resolve?
|
32
|
-
@no_resolve ||= update(resolve_self: false, resolve_class: false, resolve_instance: false)
|
33
|
-
else
|
34
|
-
self
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def resolve?
|
39
|
-
resolve_self || resolve_class || resolve_instance
|
40
|
-
end
|
41
12
|
|
42
|
-
|
43
|
-
other.is_a?(Config) &&
|
44
|
-
other.self_type == self_type &&
|
45
|
-
other.class_type == class_type &&
|
46
|
-
other.instance_type == instance_type &&
|
47
|
-
other.resolve_self == resolve_self &&
|
48
|
-
other.resolve_class == resolve_class &&
|
49
|
-
other.resolve_instance == resolve_instance &&
|
50
|
-
other.variable_bounds == variable_bounds
|
13
|
+
validate
|
51
14
|
end
|
52
15
|
|
53
|
-
|
54
|
-
|
55
|
-
def hash
|
56
|
-
self_type.hash ^ class_type.hash ^ instance_type.hash ^ resolve_self.hash ^ resolve_class.hash ^ resolve_instance.hash ^ variable_bounds.hash
|
16
|
+
def self.empty
|
17
|
+
new(self_type: nil, variable_bounds: {})
|
57
18
|
end
|
58
19
|
|
59
20
|
def subst
|
60
|
-
|
61
|
-
Substitution.build(
|
62
|
-
[],
|
63
|
-
[],
|
64
|
-
self_type: self_type,
|
65
|
-
module_type: class_type || AST::Types::Class.instance,
|
66
|
-
instance_type: instance_type || AST::Types::Instance.instance
|
67
|
-
)
|
21
|
+
if self_type || class_type || instance_type
|
22
|
+
Substitution.build([], [], self_type: self_type, module_type: class_type, instance_type: instance_type)
|
68
23
|
end
|
69
24
|
end
|
70
25
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
26
|
+
def validate
|
27
|
+
validate_fvs(:self_type, self_type)
|
28
|
+
validate_fvs(:instance_type, instance_type)
|
29
|
+
validate_fvs(:class_type, class_type)
|
30
|
+
self
|
75
31
|
end
|
76
32
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
33
|
+
def validate_fvs(name, type)
|
34
|
+
if type
|
35
|
+
fvs = type.free_variables
|
36
|
+
if fvs.include?(AST::Types::Self.instance)
|
37
|
+
raise "#{name} cannot include 'self' type: #{type}"
|
38
|
+
end
|
39
|
+
if fvs.include?(AST::Types::Instance.instance)
|
40
|
+
raise "#{name} cannot include 'instance' type: #{type}"
|
41
|
+
end
|
42
|
+
if fvs.include?(AST::Types::Class.instance)
|
43
|
+
raise "#{name} cannot include 'class' type: #{type}"
|
44
|
+
end
|
80
45
|
end
|
81
46
|
end
|
82
47
|
|
83
|
-
def
|
84
|
-
|
85
|
-
class_type
|
86
|
-
end
|
48
|
+
def upper_bound(a)
|
49
|
+
variable_bounds.fetch(a, nil)
|
87
50
|
end
|
88
51
|
end
|
89
52
|
|
90
|
-
attr_reader :factory, :
|
91
|
-
attr_reader :raw_instance_object_shape_cache, :raw_singleton_object_shape_cache, :raw_interface_object_shape_cache
|
53
|
+
attr_reader :factory, :object_shape_cache, :union_shape_cache, :singleton_shape_cache
|
92
54
|
|
93
55
|
def initialize(factory)
|
94
56
|
@factory = factory
|
95
|
-
@
|
96
|
-
@
|
97
|
-
@
|
98
|
-
@raw_interface_object_shape_cache = {}
|
57
|
+
@object_shape_cache = {}
|
58
|
+
@union_shape_cache = {}
|
59
|
+
@singleton_shape_cache = {}
|
99
60
|
end
|
100
61
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
62
|
+
def shape(type, config)
|
63
|
+
Steep.logger.tagged "shape(#{type})" do
|
64
|
+
if shape = raw_shape(type, config)
|
65
|
+
if type.free_variables.include?(AST::Types::Self.instance)
|
66
|
+
shape
|
67
|
+
else
|
68
|
+
if s = config.subst
|
69
|
+
shape.subst(s)
|
70
|
+
else
|
71
|
+
shape
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
107
75
|
end
|
108
76
|
end
|
109
77
|
|
110
|
-
def fetch_cache(
|
111
|
-
has_self = include_self?(type)
|
112
|
-
fvs = type.free_variables
|
113
|
-
|
114
|
-
# @type var key: cache_key
|
115
|
-
key = [
|
116
|
-
type,
|
117
|
-
public_only,
|
118
|
-
has_self ? config.self_type : nil,
|
119
|
-
has_self ? config.class_type : nil,
|
120
|
-
has_self ? config.instance_type : nil,
|
121
|
-
config.resolve_self,
|
122
|
-
config.resolve_class,
|
123
|
-
config.resolve_instance,
|
124
|
-
if config.variable_bounds.each_key.any? {|var| fvs.include?(var)}
|
125
|
-
config.variable_bounds.select {|var, _| fvs.include?(var) }
|
126
|
-
else
|
127
|
-
nil
|
128
|
-
end
|
129
|
-
]
|
130
|
-
|
78
|
+
def fetch_cache(cache, key)
|
131
79
|
if cache.key?(key)
|
132
|
-
cache
|
133
|
-
else
|
134
|
-
cache[key] = yield
|
80
|
+
return cache.fetch(key)
|
135
81
|
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def shape(type, public_only:, config:)
|
139
|
-
fetch_cache(type, public_only, config) do
|
140
|
-
case type
|
141
|
-
when AST::Types::Self
|
142
|
-
if self_type = config.self_type?
|
143
|
-
self_type = self_type.subst(config.subst)
|
144
|
-
shape(self_type, public_only: public_only, config: config.update(resolve_self: false))
|
145
|
-
end
|
146
|
-
when AST::Types::Instance
|
147
|
-
if instance_type = config.instance_type?
|
148
|
-
instance_type = instance_type.subst(config.subst)
|
149
|
-
shape(instance_type, public_only: public_only, config: config.update(resolve_instance: false))
|
150
|
-
end
|
151
|
-
when AST::Types::Class
|
152
|
-
if class_type = config.class_type?
|
153
|
-
class_type = class_type.subst(config.subst)
|
154
|
-
shape(class_type, public_only: public_only, config: config.update(resolve_class: false))
|
155
|
-
end
|
156
|
-
when AST::Types::Name::Instance, AST::Types::Name::Interface, AST::Types::Name::Singleton
|
157
|
-
object_shape(
|
158
|
-
type.subst(config.subst),
|
159
|
-
public_only,
|
160
|
-
!config.resolve_self,
|
161
|
-
!config.resolve_instance,
|
162
|
-
!config.resolve_class
|
163
|
-
)
|
164
|
-
when AST::Types::Name::Alias
|
165
|
-
if expanded = factory.deep_expand_alias(type)
|
166
|
-
shape(expanded, public_only: public_only, config: config)&.update(type: type)
|
167
|
-
end
|
168
|
-
when AST::Types::Any, AST::Types::Bot, AST::Types::Void, AST::Types::Top
|
169
|
-
nil
|
170
|
-
when AST::Types::Var
|
171
|
-
if bound = config.variable_bounds[type.name]
|
172
|
-
shape(bound, public_only: public_only, config: config)&.update(type: type)
|
173
|
-
end
|
174
|
-
when AST::Types::Union
|
175
|
-
if include_self?(type)
|
176
|
-
self_var = AST::Types::Var.fresh(:SELF)
|
177
|
-
class_var = AST::Types::Var.fresh(:CLASS)
|
178
|
-
instance_var = AST::Types::Var.fresh(:INSTANCE)
|
179
82
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
config_ = config.update(resolve_self: false, resolve_class: true, resolve_instance: true, variable_bounds: bounds)
|
184
|
-
|
185
|
-
shapes = type_.types.map do |type|
|
186
|
-
shape(type, public_only: public_only, config: config_) or return
|
187
|
-
end
|
83
|
+
cache[key] = yield
|
84
|
+
end
|
188
85
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
86
|
+
def raw_shape(type, config)
|
87
|
+
case type
|
88
|
+
when AST::Types::Self
|
89
|
+
self_type = config.self_type or raise
|
90
|
+
self_shape(self_type, config)
|
91
|
+
when AST::Types::Instance
|
92
|
+
instance_type = config.instance_type or raise
|
93
|
+
raw_shape(instance_type, config)
|
94
|
+
when AST::Types::Class
|
95
|
+
klass_type = config.class_type or raise
|
96
|
+
raw_shape(klass_type, config)
|
97
|
+
when AST::Types::Name::Singleton
|
98
|
+
singleton_shape(type.name).subst(class_subst(type))
|
99
|
+
when AST::Types::Name::Instance
|
100
|
+
object_shape(type.name).subst(class_subst(type).merge(app_subst(type)), type: type)
|
101
|
+
when AST::Types::Name::Interface
|
102
|
+
object_shape(type.name).subst(interface_subst(type).merge(app_subst(type)), type: type)
|
103
|
+
when AST::Types::Union
|
104
|
+
groups = type.types.group_by do |type|
|
105
|
+
if type.is_a?(AST::Types::Literal)
|
106
|
+
type.back_type
|
201
107
|
else
|
202
|
-
|
203
|
-
|
204
|
-
shapes = type.types.map do |type|
|
205
|
-
shape(type, public_only: public_only, config: config_) or return
|
206
|
-
end
|
207
|
-
|
208
|
-
if shape = union_shape(type, shapes, public_only)
|
209
|
-
shape.subst(
|
210
|
-
Substitution.build(
|
211
|
-
[], [],
|
212
|
-
self_type: type,
|
213
|
-
instance_type: AST::Builtin.any_type,
|
214
|
-
module_type: AST::Builtin.any_type
|
215
|
-
)
|
216
|
-
)
|
217
|
-
end
|
218
|
-
end
|
219
|
-
when AST::Types::Intersection
|
220
|
-
self_var = AST::Types::Var.fresh(:SELF)
|
221
|
-
class_var = AST::Types::Var.fresh(:CLASS)
|
222
|
-
instance_var = AST::Types::Var.fresh(:INSTANCE)
|
223
|
-
|
224
|
-
bounds = config.variable_bounds.merge({ self_var.name => config.self_type, instance_var.name => config.instance_type, class_var.name => config.class_type })
|
225
|
-
type_ = type.subst(Substitution.build([], [], self_type: self_var, instance_type: instance_var, module_type: class_var)) #: AST::Types::Intersection
|
226
|
-
|
227
|
-
config_ = config.update(resolve_self: false, resolve_class: true, resolve_instance: true, variable_bounds: bounds)
|
228
|
-
|
229
|
-
shapes = type_.types.map do |type|
|
230
|
-
shape(type, public_only: public_only, config: config_) or return
|
108
|
+
nil
|
231
109
|
end
|
110
|
+
end
|
232
111
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
),
|
242
|
-
type: type.subst(config.subst)
|
243
|
-
)
|
112
|
+
shapes = [] #: Array[Shape]
|
113
|
+
groups.each do |name, types|
|
114
|
+
if name
|
115
|
+
union = AST::Types::Union.build(types: types)
|
116
|
+
subst = class_subst(name).update(self_type: union)
|
117
|
+
shapes << object_shape(name.name).subst(subst, type: union)
|
118
|
+
else
|
119
|
+
shapes.concat(types.map {|ty| raw_shape(ty, config) or return })
|
244
120
|
end
|
121
|
+
end
|
245
122
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
123
|
+
fetch_cache(union_shape_cache, type) do
|
124
|
+
union_shape(type, shapes)
|
125
|
+
end
|
126
|
+
when AST::Types::Intersection
|
127
|
+
shapes = type.types.map do |type|
|
128
|
+
raw_shape(type, config) or return
|
129
|
+
end
|
130
|
+
intersection_shape(type, shapes)
|
131
|
+
when AST::Types::Name::Alias
|
132
|
+
expanded = factory.expand_alias(type)
|
133
|
+
if shape = raw_shape(expanded, config)
|
134
|
+
shape.update(type: type)
|
135
|
+
end
|
136
|
+
when AST::Types::Literal
|
137
|
+
instance_type = type.back_type
|
138
|
+
subst = class_subst(instance_type).update(self_type: type)
|
139
|
+
object_shape(instance_type.name).subst(subst, type: type)
|
140
|
+
when AST::Types::Boolean
|
141
|
+
true_shape =
|
142
|
+
(object_shape(RBS::BuiltinNames::TrueClass.name)).
|
143
|
+
subst(class_subst(AST::Builtin::TrueClass.instance_type).update(self_type: type))
|
144
|
+
false_shape =
|
145
|
+
(object_shape(RBS::BuiltinNames::FalseClass.name)).
|
146
|
+
subst(class_subst(AST::Builtin::FalseClass.instance_type).update(self_type: type))
|
147
|
+
union_shape(type, [true_shape, false_shape])
|
148
|
+
when AST::Types::Proc
|
149
|
+
shape = object_shape(AST::Builtin::Proc.module_name).subst(class_subst(AST::Builtin::Proc.instance_type).update(self_type: type))
|
150
|
+
proc_shape(type, shape)
|
151
|
+
when AST::Types::Tuple
|
152
|
+
tuple_shape(type) do |array|
|
153
|
+
object_shape(array.name).subst(
|
154
|
+
class_subst(array).update(self_type: type).merge(app_subst(array))
|
262
155
|
)
|
263
|
-
|
264
|
-
if shape
|
265
|
-
shape.subst(Substitution.build([], [], self_type: type))
|
266
|
-
end
|
267
|
-
when AST::Types::Nil
|
268
|
-
if shape = object_shape(AST::Builtin::NilClass.instance_type, public_only, true, !config.resolve_instance, !config.resolve_class)
|
269
|
-
if config.resolve_self
|
270
|
-
shape.subst(Substitution.build([], [], self_type: type), type: type)
|
271
|
-
else
|
272
|
-
shape.update(type: type)
|
273
|
-
end
|
274
|
-
end
|
275
|
-
when AST::Types::Proc
|
276
|
-
proc_shape(type, public_only, config)
|
277
|
-
else
|
278
|
-
raise "Unknown type is given: #{type}"
|
279
156
|
end
|
157
|
+
when AST::Types::Record
|
158
|
+
record_shape(type) do |hash|
|
159
|
+
object_shape(hash.name).subst(
|
160
|
+
class_subst(hash).update(self_type: type).merge(app_subst(hash))
|
161
|
+
)
|
162
|
+
end
|
163
|
+
when AST::Types::Var
|
164
|
+
if bound = config.upper_bound(type.name)
|
165
|
+
new_config = Config.new(self_type: bound, variable_bounds: config.variable_bounds)
|
166
|
+
sub = Substitution.build([], self_type: type)
|
167
|
+
# We have to use `self_shape` insead of `raw_shape` here.
|
168
|
+
# Keep the `self` types included in the `bound`'s shape, and replace it to the type variable.
|
169
|
+
self_shape(bound, new_config)&.subst(sub, type: type)
|
170
|
+
end
|
171
|
+
when AST::Types::Nil
|
172
|
+
subst = class_subst(AST::Builtin::NilClass.instance_type).update(self_type: type)
|
173
|
+
object_shape(AST::Builtin::NilClass.module_name).subst(subst, type: type)
|
174
|
+
when AST::Types::Logic::Base
|
175
|
+
true_shape =
|
176
|
+
(object_shape(RBS::BuiltinNames::TrueClass.name)).
|
177
|
+
subst(class_subst(AST::Builtin::TrueClass.instance_type).update(self_type: type))
|
178
|
+
false_shape =
|
179
|
+
(object_shape(RBS::BuiltinNames::FalseClass.name)).
|
180
|
+
subst(class_subst(AST::Builtin::FalseClass.instance_type).update(self_type: type))
|
181
|
+
union_shape(type, [true_shape, false_shape])
|
182
|
+
else
|
183
|
+
nil
|
280
184
|
end
|
281
185
|
end
|
282
186
|
|
283
|
-
def
|
284
|
-
factory.definition_builder
|
285
|
-
end
|
286
|
-
|
287
|
-
def object_shape(type, public_only, keep_self, keep_instance, keep_singleton)
|
187
|
+
def self_shape(type, config)
|
288
188
|
case type
|
189
|
+
when AST::Types::Self, AST::Types::Instance, AST::Types::Class
|
190
|
+
raise
|
191
|
+
when AST::Types::Name::Singleton
|
192
|
+
singleton_shape(type.name).subst(class_subst(type).update(self_type: nil))
|
289
193
|
when AST::Types::Name::Instance
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
module_type: keep_singleton ? AST::Types::Class.instance : AST::Types::Name::Singleton.new(name: type.name),
|
296
|
-
instance_type: keep_instance ? AST::Types::Instance.instance : factory.instance_type(type.name)
|
297
|
-
)
|
194
|
+
object_shape(type.name)
|
195
|
+
.subst(
|
196
|
+
class_subst(type).update(self_type: nil).merge(app_subst(type)),
|
197
|
+
type: type
|
198
|
+
)
|
298
199
|
when AST::Types::Name::Interface
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
200
|
+
object_shape(type.name).subst(app_subst(type), type: type)
|
201
|
+
when AST::Types::Literal
|
202
|
+
instance_type = type.back_type
|
203
|
+
subst = class_subst(instance_type).update(self_type: nil)
|
204
|
+
object_shape(instance_type.name).subst(subst, type: type)
|
205
|
+
when AST::Types::Boolean
|
206
|
+
true_shape =
|
207
|
+
(object_shape(RBS::BuiltinNames::TrueClass.name)).
|
208
|
+
subst(class_subst(AST::Builtin::TrueClass.instance_type).update(self_type: nil))
|
209
|
+
false_shape =
|
210
|
+
(object_shape(RBS::BuiltinNames::FalseClass.name)).
|
211
|
+
subst(class_subst(AST::Builtin::FalseClass.instance_type).update(self_type: nil))
|
212
|
+
union_shape(type, [true_shape, false_shape])
|
213
|
+
when AST::Types::Proc
|
214
|
+
shape = object_shape(AST::Builtin::Proc.module_name).subst(class_subst(AST::Builtin::Proc.instance_type).update(self_type: nil))
|
215
|
+
proc_shape(type, shape)
|
216
|
+
when AST::Types::Var
|
217
|
+
if bound = config.upper_bound(type.name)
|
218
|
+
self_shape(bound, config)&.update(type: type)
|
219
|
+
end
|
220
|
+
else
|
221
|
+
raw_shape(type, config)
|
313
222
|
end
|
314
|
-
|
315
|
-
raw_object_shape(type, public_only, subst)
|
316
223
|
end
|
317
224
|
|
318
|
-
def
|
319
|
-
|
225
|
+
def app_subst(type)
|
226
|
+
if type.args.empty?
|
227
|
+
return Substitution.empty
|
228
|
+
end
|
229
|
+
|
230
|
+
vars =
|
320
231
|
case type
|
321
232
|
when AST::Types::Name::Instance
|
322
|
-
|
233
|
+
entry = factory.env.normalized_module_class_entry(type.name) or raise
|
234
|
+
entry.primary.decl.type_params.map { _1.name }
|
323
235
|
when AST::Types::Name::Interface
|
324
|
-
|
325
|
-
|
326
|
-
|
236
|
+
entry = factory.env.interface_decls.fetch(type.name)
|
237
|
+
entry.decl.type_params.map { _1.name }
|
238
|
+
when AST::Types::Name::Alias
|
239
|
+
entry = factory.env.type_alias_decls.fetch(type.name)
|
240
|
+
entry.decl.type_params.map { _1.name }
|
327
241
|
end
|
328
242
|
|
329
|
-
|
330
|
-
|
243
|
+
Substitution.build(vars, type.args)
|
244
|
+
end
|
331
245
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
246
|
+
def class_subst(type)
|
247
|
+
case type
|
248
|
+
when AST::Types::Name::Singleton
|
249
|
+
self_type = type
|
250
|
+
singleton_type = type
|
251
|
+
instance_type = factory.instance_type(type.name)
|
252
|
+
when AST::Types::Name::Instance
|
253
|
+
self_type = type
|
254
|
+
singleton_type = type.to_module
|
255
|
+
instance_type = factory.instance_type(type.name)
|
256
|
+
end
|
257
|
+
|
258
|
+
Substitution.build([], self_type: self_type, module_type: singleton_type, instance_type: instance_type)
|
259
|
+
end
|
260
|
+
|
261
|
+
def interface_subst(type)
|
262
|
+
Substitution.build([], self_type: type)
|
263
|
+
end
|
264
|
+
|
265
|
+
def singleton_shape(type_name)
|
266
|
+
singleton_shape_cache[type_name] ||= begin
|
267
|
+
shape = Interface::Shape.new(type: AST::Types::Name::Singleton.new(name: type_name), private: true)
|
268
|
+
definition = factory.definition_builder.build_singleton(type_name)
|
340
269
|
|
341
270
|
definition.methods.each do |name, method|
|
342
|
-
|
271
|
+
Steep.logger.tagged "method = #{type_name}.#{name}" do
|
272
|
+
shape.methods[name] = Interface::Shape::Entry.new(
|
273
|
+
private_method: method.private?,
|
274
|
+
method_types: method.defs.map do |type_def|
|
275
|
+
method_name = method_name_for(type_def, name)
|
276
|
+
decl = TypeInference::MethodCall::MethodDecl.new(method_name: method_name, method_def: type_def)
|
277
|
+
method_type = factory.method_type(type_def.type, method_decls: Set[decl])
|
278
|
+
replace_primitive_method(method_name, type_def, method_type)
|
279
|
+
end
|
280
|
+
)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
shape
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def object_shape(type_name)
|
289
|
+
object_shape_cache[type_name] ||= begin
|
290
|
+
shape = Interface::Shape.new(type: AST::Builtin.bottom_type, private: true)
|
291
|
+
|
292
|
+
case
|
293
|
+
when type_name.class?
|
294
|
+
definition = factory.definition_builder.build_instance(type_name)
|
295
|
+
when type_name.interface?
|
296
|
+
definition = factory.definition_builder.build_interface(type_name)
|
297
|
+
end
|
343
298
|
|
344
|
-
|
299
|
+
definition or raise
|
300
|
+
|
301
|
+
definition.methods.each do |name, method|
|
302
|
+
Steep.logger.tagged "method = #{type_name}##{name}" do
|
345
303
|
shape.methods[name] = Interface::Shape::Entry.new(
|
304
|
+
private_method: method.private?,
|
346
305
|
method_types: method.defs.map do |type_def|
|
347
306
|
method_name = method_name_for(type_def, name)
|
348
307
|
decl = TypeInference::MethodCall::MethodDecl.new(method_name: method_name, method_def: type_def)
|
@@ -355,8 +314,84 @@ module Steep
|
|
355
314
|
|
356
315
|
shape
|
357
316
|
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def union_shape(shape_type, shapes)
|
320
|
+
s0, *sx = shapes
|
321
|
+
s0 or raise
|
322
|
+
all_common_methods = Set.new(s0.methods.each_name)
|
323
|
+
sx.each do |shape|
|
324
|
+
all_common_methods &= shape.methods.each_name
|
325
|
+
end
|
326
|
+
|
327
|
+
shape = Interface::Shape.new(type: shape_type, private: true)
|
328
|
+
all_common_methods.each do |method_name|
|
329
|
+
method_typess = [] #: Array[Array[MethodType]]
|
330
|
+
private_method = false
|
331
|
+
shapes.each do |shape|
|
332
|
+
entry = shape.methods[method_name] || raise
|
333
|
+
method_typess << entry.method_types
|
334
|
+
private_method ||= entry.private_method?
|
335
|
+
end
|
336
|
+
|
337
|
+
shape.methods[method_name] = Interface::Shape::Entry.new(private_method: private_method) do
|
338
|
+
method_typess.inject do |types1, types2|
|
339
|
+
# @type break: nil
|
340
|
+
|
341
|
+
if types1 == types2
|
342
|
+
decl_array1 = types1.map(&:method_decls)
|
343
|
+
decl_array2 = types2.map(&:method_decls)
|
344
|
+
|
345
|
+
if decl_array1 == decl_array2
|
346
|
+
next types1
|
347
|
+
end
|
348
|
+
|
349
|
+
decls1 = decl_array1.each.with_object(Set[]) {|array, decls| decls.merge(array) } #$ Set[TypeInference::MethodCall::MethodDecl]
|
350
|
+
decls2 = decl_array2.each.with_object(Set[]) {|array, decls| decls.merge(array) } #$ Set[TypeInference::MethodCall::MethodDecl]
|
351
|
+
|
352
|
+
if decls1 == decls2
|
353
|
+
next types1
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
method_types = {} #: Hash[MethodType, bool]
|
358
|
+
|
359
|
+
types1.each do |type1|
|
360
|
+
types2.each do |type2|
|
361
|
+
if type1 == type2
|
362
|
+
method_types[type1.with(method_decls: type1.method_decls + type2.method_decls)] = true
|
363
|
+
else
|
364
|
+
if type = MethodType.union(type1, type2, subtyping)
|
365
|
+
method_types[type] = true
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
break nil if method_types.empty?
|
372
|
+
|
373
|
+
method_types.keys
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
shape
|
379
|
+
end
|
380
|
+
|
381
|
+
def intersection_shape(type, shapes)
|
382
|
+
shape = Interface::Shape.new(type: type, private: true)
|
383
|
+
|
384
|
+
shapes.each do |s|
|
385
|
+
shape.methods.merge!(s.methods) do |name, old_entry, new_entry|
|
386
|
+
if old_entry.public_method? && new_entry.private_method?
|
387
|
+
old_entry
|
388
|
+
else
|
389
|
+
new_entry
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
358
393
|
|
359
|
-
|
394
|
+
shape
|
360
395
|
end
|
361
396
|
|
362
397
|
def method_name_for(type_def, name)
|
@@ -383,63 +418,19 @@ module Steep
|
|
383
418
|
@subtyping ||= Subtyping::Check.new(builder: self)
|
384
419
|
end
|
385
420
|
|
386
|
-
def
|
387
|
-
shapes.inject do |shape1, shape2|
|
388
|
-
Interface::Shape.new(type: shape_type, private: !public_only).tap do |shape|
|
389
|
-
common_methods = Set.new(shape1.methods.each_name) & Set.new(shape2.methods.each_name)
|
390
|
-
common_methods.each do |name|
|
391
|
-
Steep.logger.tagged(name.to_s) do
|
392
|
-
types1 = shape1.methods[name]&.method_types or raise
|
393
|
-
types2 = shape2.methods[name]&.method_types or raise
|
394
|
-
|
395
|
-
if types1 == types2 && types1.map {|type| type.method_decls.to_a }.to_set == types2.map {|type| type.method_decls.to_a }.to_set
|
396
|
-
shape.methods[name] = (shape1.methods[name] or raise)
|
397
|
-
else
|
398
|
-
method_types = {} #: Hash[MethodType, true]
|
399
|
-
|
400
|
-
types1.each do |type1|
|
401
|
-
types2.each do |type2|
|
402
|
-
if type1 == type2
|
403
|
-
method_types[type1.with(method_decls: type1.method_decls + type2.method_decls)] = true
|
404
|
-
else
|
405
|
-
if type = MethodType.union(type1, type2, subtyping)
|
406
|
-
method_types[type] = true
|
407
|
-
end
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
unless method_types.empty?
|
413
|
-
shape.methods[name] = Interface::Shape::Entry.new(method_types: method_types.keys)
|
414
|
-
end
|
415
|
-
end
|
416
|
-
end
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
def intersection_shape(type, shapes, public_only)
|
423
|
-
shapes.inject do |shape1, shape2|
|
424
|
-
Interface::Shape.new(type: type, private: !public_only).tap do |shape|
|
425
|
-
shape.methods.merge!(shape1.methods)
|
426
|
-
shape.methods.merge!(shape2.methods)
|
427
|
-
end
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
def tuple_shape(tuple, public_only, config)
|
421
|
+
def tuple_shape(tuple)
|
432
422
|
element_type = AST::Types::Union.build(types: tuple.types, location: nil)
|
433
423
|
array_type = AST::Builtin::Array.instance_type(element_type)
|
434
424
|
|
435
|
-
array_shape =
|
436
|
-
shape = Shape.new(type: tuple, private:
|
425
|
+
array_shape = yield(array_type) or raise
|
426
|
+
shape = Shape.new(type: tuple, private: true)
|
437
427
|
shape.methods.merge!(array_shape.methods)
|
438
428
|
|
439
429
|
aref_entry = array_shape.methods[:[]].yield_self do |aref|
|
440
430
|
raise unless aref
|
441
431
|
|
442
432
|
Shape::Entry.new(
|
433
|
+
private_method: false,
|
443
434
|
method_types: tuple.types.map.with_index {|elem_type, index|
|
444
435
|
MethodType.new(
|
445
436
|
type_params: [],
|
@@ -459,6 +450,7 @@ module Steep
|
|
459
450
|
raise unless update
|
460
451
|
|
461
452
|
Shape::Entry.new(
|
453
|
+
private_method: false,
|
462
454
|
method_types: tuple.types.map.with_index {|elem_type, index|
|
463
455
|
MethodType.new(
|
464
456
|
type_params: [],
|
@@ -478,6 +470,7 @@ module Steep
|
|
478
470
|
raise unless fetch
|
479
471
|
|
480
472
|
Shape::Entry.new(
|
473
|
+
private_method: false,
|
481
474
|
method_types: tuple.types.flat_map.with_index {|elem_type, index|
|
482
475
|
[
|
483
476
|
MethodType.new(
|
@@ -530,6 +523,7 @@ module Steep
|
|
530
523
|
|
531
524
|
first_entry = array_shape.methods[:first].yield_self do |first|
|
532
525
|
Shape::Entry.new(
|
526
|
+
private_method: false,
|
533
527
|
method_types: [
|
534
528
|
MethodType.new(
|
535
529
|
type_params: [],
|
@@ -547,6 +541,7 @@ module Steep
|
|
547
541
|
|
548
542
|
last_entry = array_shape.methods[:last].yield_self do |last|
|
549
543
|
Shape::Entry.new(
|
544
|
+
private_method: false,
|
550
545
|
method_types: [
|
551
546
|
MethodType.new(
|
552
547
|
type_params: [],
|
@@ -568,17 +563,10 @@ module Steep
|
|
568
563
|
shape.methods[:first] = first_entry
|
569
564
|
shape.methods[:last] = last_entry
|
570
565
|
|
571
|
-
shape
|
572
|
-
Substitution.build(
|
573
|
-
[], [],
|
574
|
-
self_type: config.resolve_self ? tuple : AST::Types::Self.instance,
|
575
|
-
instance_type: AST::Builtin::Array.instance_type(fill_untyped: true),
|
576
|
-
module_type: AST::Builtin::Array.module_type
|
577
|
-
)
|
578
|
-
)
|
566
|
+
shape
|
579
567
|
end
|
580
568
|
|
581
|
-
def record_shape(record
|
569
|
+
def record_shape(record)
|
582
570
|
all_key_type = AST::Types::Union.build(
|
583
571
|
types: record.elements.each_key.map {|value| AST::Types::Literal.new(value: value, location: nil) },
|
584
572
|
location: nil
|
@@ -586,13 +574,14 @@ module Steep
|
|
586
574
|
all_value_type = AST::Types::Union.build(types: record.elements.values, location: nil)
|
587
575
|
hash_type = AST::Builtin::Hash.instance_type(all_key_type, all_value_type)
|
588
576
|
|
589
|
-
hash_shape =
|
590
|
-
shape = Shape.new(type: record, private:
|
577
|
+
hash_shape = yield(hash_type) or raise
|
578
|
+
shape = Shape.new(type: record, private: true)
|
591
579
|
shape.methods.merge!(hash_shape.methods)
|
592
580
|
|
593
581
|
shape.methods[:[]] = hash_shape.methods[:[]].yield_self do |aref|
|
594
582
|
aref or raise
|
595
583
|
Shape::Entry.new(
|
584
|
+
private_method: false,
|
596
585
|
method_types: record.elements.map do |key_value, value_type|
|
597
586
|
key_type = AST::Types::Literal.new(value: key_value, location: nil)
|
598
587
|
|
@@ -614,6 +603,7 @@ module Steep
|
|
614
603
|
update or raise
|
615
604
|
|
616
605
|
Shape::Entry.new(
|
606
|
+
private_method: false,
|
617
607
|
method_types: record.elements.map do |key_value, value_type|
|
618
608
|
key_type = AST::Types::Literal.new(value: key_value, location: nil)
|
619
609
|
MethodType.new(
|
@@ -633,6 +623,7 @@ module Steep
|
|
633
623
|
update or raise
|
634
624
|
|
635
625
|
Shape::Entry.new(
|
626
|
+
private_method: false,
|
636
627
|
method_types: record.elements.flat_map {|key_value, value_type|
|
637
628
|
key_type = AST::Types::Literal.new(value: key_value, location: nil)
|
638
629
|
|
@@ -680,34 +671,19 @@ module Steep
|
|
680
671
|
)
|
681
672
|
end
|
682
673
|
|
683
|
-
shape
|
684
|
-
Substitution.build(
|
685
|
-
[], [],
|
686
|
-
self_type: config.resolve_self ? record : AST::Types::Self.instance,
|
687
|
-
instance_type: AST::Builtin::Hash.instance_type(fill_untyped: true),
|
688
|
-
module_type: AST::Builtin::Hash.module_type
|
689
|
-
)
|
690
|
-
)
|
674
|
+
shape
|
691
675
|
end
|
692
676
|
|
693
|
-
def proc_shape(proc,
|
694
|
-
|
695
|
-
|
696
|
-
shape = Shape.new(type: proc, private: !public_only)
|
677
|
+
def proc_shape(proc, proc_shape)
|
678
|
+
shape = Shape.new(type: proc, private: true)
|
697
679
|
shape.methods.merge!(proc_shape.methods)
|
698
680
|
|
699
681
|
shape.methods[:[]] = shape.methods[:call] = Shape::Entry.new(
|
682
|
+
private_method: false,
|
700
683
|
method_types: [MethodType.new(type_params: [], type: proc.type, block: proc.block, method_decls: Set[])]
|
701
684
|
)
|
702
685
|
|
703
|
-
shape
|
704
|
-
Substitution.build(
|
705
|
-
[], [],
|
706
|
-
self_type: config.resolve_self ? proc : AST::Types::Self.instance,
|
707
|
-
instance_type: AST::Builtin::Proc.instance_type(fill_untyped: true),
|
708
|
-
module_type: AST::Builtin::Proc.module_type
|
709
|
-
)
|
710
|
-
)
|
686
|
+
shape
|
711
687
|
end
|
712
688
|
|
713
689
|
def replace_primitive_method(method_name, method_def, method_type)
|