steep 1.7.0.dev.2 → 1.7.0.dev.3
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/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)
|