steep 0.4.0 → 0.5.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 +12 -0
- data/LICENSE +21 -0
- data/bin/smoke_runner.rb +3 -0
- data/lib/steep/ast/annotation/collection.rb +120 -43
- data/lib/steep/ast/annotation.rb +5 -10
- data/lib/steep/ast/location.rb +1 -1
- data/lib/steep/ast/method_type.rb +3 -1
- data/lib/steep/ast/signature/alias.rb +19 -0
- data/lib/steep/ast/signature/env.rb +9 -0
- data/lib/steep/ast/signature/members.rb +4 -0
- data/lib/steep/ast/types/proc.rb +79 -0
- data/lib/steep/ast/types/void.rb +4 -0
- data/lib/steep/cli.rb +2 -1
- data/lib/steep/drivers/check.rb +4 -1
- data/lib/steep/errors.rb +13 -0
- data/lib/steep/interface/builder.rb +90 -47
- data/lib/steep/interface/instantiated.rb +1 -1
- data/lib/steep/interface/method.rb +8 -0
- data/lib/steep/interface/method_type.rb +40 -13
- data/lib/steep/parser.rb +1098 -1043
- data/lib/steep/parser.y +94 -36
- data/lib/steep/source.rb +5 -6
- data/lib/steep/subtyping/check.rb +162 -47
- data/lib/steep/subtyping/variable_occurrence.rb +2 -2
- data/lib/steep/subtyping/variable_variance.rb +3 -3
- data/lib/steep/type_construction.rb +630 -300
- data/lib/steep/type_inference/block_params.rb +186 -35
- data/lib/steep/type_inference/send_args.rb +12 -3
- data/lib/steep/type_inference/type_env.rb +10 -4
- data/lib/steep/type_name.rb +6 -0
- data/lib/steep/typing.rb +21 -2
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +2 -0
- data/smoke/alias/a.rb +19 -0
- data/smoke/alias/a.rbi +10 -0
- data/smoke/alias/b.rb +7 -0
- data/smoke/alias/c.rb +10 -0
- data/smoke/array/c.rb +7 -0
- data/smoke/block/c.rb +10 -0
- data/smoke/block/c.rbi +3 -0
- data/smoke/block/d.rb +15 -0
- data/smoke/class/c.rb +1 -1
- data/smoke/class/e.rb +1 -1
- data/smoke/class/h.rb +15 -0
- data/smoke/class/h.rbi +7 -0
- data/smoke/class/i.rb +17 -0
- data/smoke/class/i.rbi +9 -0
- data/smoke/extension/a.rbi +4 -0
- data/smoke/extension/d.rb +2 -0
- data/smoke/hash/a.rb +17 -0
- data/smoke/hash/b.rb +7 -0
- data/smoke/implements/a.rb +2 -2
- data/smoke/initialize/a.rb +1 -1
- data/smoke/lambda/a.rb +11 -0
- data/smoke/literal/b.rb +9 -0
- data/smoke/literal/literal_methods.rbi +4 -0
- data/smoke/method/c.rb +5 -0
- data/smoke/regression/array.rb +7 -0
- data/smoke/regression/hash.rb +7 -0
- data/smoke/regression/set_divide.rb +16 -0
- data/smoke/self/a.rb +2 -2
- data/stdlib/builtin.rbi +151 -1
- data/steep.gemspec +1 -0
- metadata +30 -4
@@ -73,6 +73,12 @@ module Steep
|
|
73
73
|
types: type.types.map {|ty| absolute_type(ty, current:current) },
|
74
74
|
location: type.location
|
75
75
|
)
|
76
|
+
when AST::Types::Proc
|
77
|
+
AST::Types::Proc.new(
|
78
|
+
params: type.params.map_type {|ty| absolute_type(ty, current: current) },
|
79
|
+
return_type: absolute_type(type.return_type, current: current),
|
80
|
+
location: type.location
|
81
|
+
)
|
76
82
|
else
|
77
83
|
type
|
78
84
|
end
|
@@ -137,7 +143,7 @@ module Steep
|
|
137
143
|
merge_ivars ivars, instantiated.ivars
|
138
144
|
end
|
139
145
|
|
140
|
-
def add_method(type_name, method, methods:)
|
146
|
+
def add_method(type_name, method, methods:, extra_attributes: [])
|
141
147
|
super_method = methods[method.name]
|
142
148
|
new_method = Method.new(
|
143
149
|
type_name: type_name,
|
@@ -146,7 +152,7 @@ module Steep
|
|
146
152
|
method_type_to_method_type(method_type, current: type_name.name)
|
147
153
|
end,
|
148
154
|
super_method: super_method,
|
149
|
-
attributes: method.attributes
|
155
|
+
attributes: method.attributes + extra_attributes
|
150
156
|
)
|
151
157
|
|
152
158
|
methods[method.name] = if super_method&.include_in_chain?(new_method)
|
@@ -243,6 +249,17 @@ module Steep
|
|
243
249
|
end
|
244
250
|
end
|
245
251
|
|
252
|
+
signatures.find_extensions(sig.name).each do |ext|
|
253
|
+
ext.members.each do |member|
|
254
|
+
case member
|
255
|
+
when AST::Signature::Members::Method
|
256
|
+
if member.module_method?
|
257
|
+
add_method(type_name, member, methods: methods)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
246
263
|
unless constructor
|
247
264
|
methods.delete(:new)
|
248
265
|
end
|
@@ -261,6 +278,7 @@ module Steep
|
|
261
278
|
|
262
279
|
supers = [sig.self_type].compact.map {|type| absolute_type(type, current: nil) }
|
263
280
|
methods = {}
|
281
|
+
ivar_chains = {}
|
264
282
|
|
265
283
|
module_instance = build(TypeName::Instance.new(name: ModuleName.parse("::Module")))
|
266
284
|
instantiated = module_instance.instantiate(
|
@@ -277,14 +295,14 @@ module Steep
|
|
277
295
|
merge_mixin(TypeName::Module.new(name: member.name),
|
278
296
|
member.args.map {|type| absolute_type(type, current: sig.name) },
|
279
297
|
methods: methods,
|
280
|
-
ivars:
|
298
|
+
ivars: ivar_chains,
|
281
299
|
supers: supers,
|
282
300
|
current: sig.name)
|
283
301
|
when AST::Signature::Members::Extend
|
284
302
|
merge_mixin(TypeName::Instance.new(name: member.name),
|
285
303
|
member.args.map {|type| absolute_type(type, current: sig.name) },
|
286
304
|
methods: methods,
|
287
|
-
ivars:
|
305
|
+
ivars: ivar_chains,
|
288
306
|
supers: supers,
|
289
307
|
current: sig.name)
|
290
308
|
end
|
@@ -296,6 +314,22 @@ module Steep
|
|
296
314
|
if member.module_method?
|
297
315
|
add_method(type_name, member, methods: methods)
|
298
316
|
end
|
317
|
+
when AST::Signature::Members::Ivar
|
318
|
+
merge_ivars(ivar_chains,
|
319
|
+
{ member.name => absolute_type(member.type, current: sig.name) })
|
320
|
+
when AST::Signature::Members::Attr
|
321
|
+
merge_attribute(sig, ivar_chains, methods, type_name, member)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
signatures.find_extensions(sig.name).each do |ext|
|
326
|
+
ext.members.each do |member|
|
327
|
+
case member
|
328
|
+
when AST::Signature::Members::Method
|
329
|
+
if member.module_method?
|
330
|
+
add_method(type_name, member, methods: methods)
|
331
|
+
end
|
332
|
+
end
|
299
333
|
end
|
300
334
|
end
|
301
335
|
|
@@ -304,7 +338,7 @@ module Steep
|
|
304
338
|
params: [],
|
305
339
|
methods: methods,
|
306
340
|
supers: supers,
|
307
|
-
ivar_chains:
|
341
|
+
ivar_chains: ivar_chains
|
308
342
|
)
|
309
343
|
end
|
310
344
|
|
@@ -319,7 +353,7 @@ module Steep
|
|
319
353
|
if sig.is_a?(AST::Signature::Class)
|
320
354
|
unless sig.name == ModuleName.parse("::BasicObject")
|
321
355
|
super_class_name = sig.super_class&.name || ModuleName.parse("::Object")
|
322
|
-
super_class_interface = build(TypeName::Instance.new(name: super_class_name), current: nil)
|
356
|
+
super_class_interface = build(TypeName::Instance.new(name: super_class_name), current: nil, with_initialize: with_initialize)
|
323
357
|
|
324
358
|
supers.push(*super_class_interface.supers)
|
325
359
|
instantiated = super_class_interface.instantiate(
|
@@ -357,51 +391,15 @@ module Steep
|
|
357
391
|
when AST::Signature::Members::Method
|
358
392
|
if member.instance_method?
|
359
393
|
if with_initialize || member.name != :initialize
|
360
|
-
|
394
|
+
extra_attrs = member.name == :initialize ? [:incompatible] : []
|
395
|
+
add_method(type_name, member, methods: methods, extra_attributes: extra_attrs)
|
361
396
|
end
|
362
397
|
end
|
363
398
|
when AST::Signature::Members::Ivar
|
364
399
|
merge_ivars(ivar_chains,
|
365
400
|
{ member.name => absolute_type(member.type, current: sig.name) })
|
366
401
|
when AST::Signature::Members::Attr
|
367
|
-
|
368
|
-
ivar_name = member.ivar || "@#{member.name}".to_sym
|
369
|
-
merge_ivars(ivar_chains,
|
370
|
-
{ ivar_name => absolute_type(member.type, current: sig.name) })
|
371
|
-
end
|
372
|
-
|
373
|
-
reader_method = AST::Signature::Members::Method.new(
|
374
|
-
location: member.location,
|
375
|
-
name: member.name,
|
376
|
-
kind: :instance,
|
377
|
-
types: [
|
378
|
-
AST::MethodType.new(location: member.type.location,
|
379
|
-
type_params: nil,
|
380
|
-
params: nil,
|
381
|
-
block: nil,
|
382
|
-
return_type: member.type)
|
383
|
-
],
|
384
|
-
attributes: []
|
385
|
-
)
|
386
|
-
add_method(type_name, reader_method, methods: methods)
|
387
|
-
|
388
|
-
if member.accessor?
|
389
|
-
writer_method = AST::Signature::Members::Method.new(
|
390
|
-
location: member.location,
|
391
|
-
name: "#{member.name}=".to_sym,
|
392
|
-
kind: :instance,
|
393
|
-
types: [
|
394
|
-
AST::MethodType.new(location: member.type.location,
|
395
|
-
type_params: nil,
|
396
|
-
params: AST::MethodType::Params::Required.new(location: member.type.location,
|
397
|
-
type: member.type),
|
398
|
-
block: nil,
|
399
|
-
return_type: member.type)
|
400
|
-
],
|
401
|
-
attributes: []
|
402
|
-
)
|
403
|
-
add_method(type_name, writer_method, methods: methods)
|
404
|
-
end
|
402
|
+
merge_attribute(sig, ivar_chains, methods, type_name, member)
|
405
403
|
end
|
406
404
|
end
|
407
405
|
|
@@ -425,6 +423,47 @@ module Steep
|
|
425
423
|
)
|
426
424
|
end
|
427
425
|
|
426
|
+
def merge_attribute(sig, ivar_chains, methods, type_name, member)
|
427
|
+
if member.ivar != false
|
428
|
+
ivar_name = member.ivar || "@#{member.name}".to_sym
|
429
|
+
merge_ivars(ivar_chains,
|
430
|
+
{ ivar_name => absolute_type(member.type, current: sig.name) })
|
431
|
+
end
|
432
|
+
|
433
|
+
reader_method = AST::Signature::Members::Method.new(
|
434
|
+
location: member.location,
|
435
|
+
name: member.name,
|
436
|
+
kind: :instance,
|
437
|
+
types: [
|
438
|
+
AST::MethodType.new(location: member.type.location,
|
439
|
+
type_params: nil,
|
440
|
+
params: nil,
|
441
|
+
block: nil,
|
442
|
+
return_type: member.type)
|
443
|
+
],
|
444
|
+
attributes: []
|
445
|
+
)
|
446
|
+
add_method(type_name, reader_method, methods: methods)
|
447
|
+
|
448
|
+
if member.accessor?
|
449
|
+
writer_method = AST::Signature::Members::Method.new(
|
450
|
+
location: member.location,
|
451
|
+
name: "#{member.name}=".to_sym,
|
452
|
+
kind: :instance,
|
453
|
+
types: [
|
454
|
+
AST::MethodType.new(location: member.type.location,
|
455
|
+
type_params: nil,
|
456
|
+
params: AST::MethodType::Params::Required.new(location: member.type.location,
|
457
|
+
type: member.type),
|
458
|
+
block: nil,
|
459
|
+
return_type: member.type)
|
460
|
+
],
|
461
|
+
attributes: []
|
462
|
+
)
|
463
|
+
add_method(type_name, writer_method, methods: methods)
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
428
467
|
def merge_ivars(dest, new_vars)
|
429
468
|
new_vars.each do |name, new_type|
|
430
469
|
dest[name] = IvarChain.new(type: new_type, parent: dest[name])
|
@@ -460,8 +499,12 @@ module Steep
|
|
460
499
|
type_params = method_type.type_params&.variables || []
|
461
500
|
params = params_to_params(method_type.params, current: current)
|
462
501
|
block = method_type.block && Block.new(
|
463
|
-
|
464
|
-
|
502
|
+
type: AST::Types::Proc.new(
|
503
|
+
params: params_to_params(method_type.block.params, current: current),
|
504
|
+
return_type: absolute_type(method_type.block.return_type, current: current),
|
505
|
+
location: method_type.block.location,
|
506
|
+
),
|
507
|
+
optional: method_type.block.optional
|
465
508
|
)
|
466
509
|
|
467
510
|
MethodType.new(
|
@@ -24,6 +24,10 @@ module Steep
|
|
24
24
|
other.attributes == attributes
|
25
25
|
end
|
26
26
|
|
27
|
+
def incompatible?
|
28
|
+
attributes.include?(:incompatible)
|
29
|
+
end
|
30
|
+
|
27
31
|
def closed?
|
28
32
|
types.all?(&:closed?)
|
29
33
|
end
|
@@ -58,6 +62,10 @@ module Steep
|
|
58
62
|
)
|
59
63
|
end
|
60
64
|
|
65
|
+
def map_types
|
66
|
+
with_types(types.map {|type| yield type })
|
67
|
+
end
|
68
|
+
|
61
69
|
def include_in_chain?(method)
|
62
70
|
(method.type_name == type_name &&
|
63
71
|
method.name == name &&
|
@@ -17,6 +17,18 @@ module Steep
|
|
17
17
|
@rest_keywords = rest_keywords
|
18
18
|
end
|
19
19
|
|
20
|
+
NONE = Object.new
|
21
|
+
def update(required: NONE, optional: NONE, rest: NONE, required_keywords: NONE, optional_keywords: NONE, rest_keywords: NONE)
|
22
|
+
self.class.new(
|
23
|
+
required: required.equal?(NONE) ? self.required : required,
|
24
|
+
optional: optional.equal?(NONE) ? self.optional : optional,
|
25
|
+
rest: rest.equal?(NONE) ? self.rest : rest,
|
26
|
+
required_keywords: required_keywords.equal?(NONE) ? self.required_keywords : required_keywords,
|
27
|
+
optional_keywords: optional_keywords.equal?(NONE) ? self.optional_keywords : optional_keywords,
|
28
|
+
rest_keywords: rest_keywords.equal?(NONE) ? self.rest_keywords : rest_keywords
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
20
32
|
def self.empty
|
21
33
|
self.new(
|
22
34
|
required: [],
|
@@ -176,38 +188,53 @@ module Steep
|
|
176
188
|
rest_keywords = self.rest_keywords ? ["**#{self.rest_keywords}"] : []
|
177
189
|
"(#{(required + optional + rest + required_keywords + optional_keywords + rest_keywords).join(", ")})"
|
178
190
|
end
|
191
|
+
|
192
|
+
def map_type(&block)
|
193
|
+
self.class.new(
|
194
|
+
required: required.map(&block),
|
195
|
+
optional: optional.map(&block),
|
196
|
+
rest: rest && yield(rest),
|
197
|
+
required_keywords: required_keywords.transform_values(&block),
|
198
|
+
optional_keywords: optional_keywords.transform_values(&block),
|
199
|
+
rest_keywords: rest_keywords && yield(rest_keywords)
|
200
|
+
)
|
201
|
+
end
|
179
202
|
end
|
180
203
|
|
181
204
|
class Block
|
182
|
-
attr_reader :
|
183
|
-
attr_reader :
|
205
|
+
attr_reader :type
|
206
|
+
attr_reader :optional
|
184
207
|
|
185
|
-
def initialize(
|
186
|
-
@
|
187
|
-
@
|
208
|
+
def initialize(type:, optional:)
|
209
|
+
@type = type
|
210
|
+
@optional = optional
|
211
|
+
end
|
212
|
+
|
213
|
+
def optional?
|
214
|
+
@optional
|
188
215
|
end
|
189
216
|
|
190
217
|
def ==(other)
|
191
|
-
other.is_a?(self.class) && other.
|
218
|
+
other.is_a?(self.class) && other.type == type && other.optional == optional
|
192
219
|
end
|
193
220
|
|
194
221
|
def closed?
|
195
|
-
|
222
|
+
type.closed?
|
196
223
|
end
|
197
224
|
|
198
225
|
def subst(s)
|
199
226
|
self.class.new(
|
200
|
-
|
201
|
-
|
227
|
+
type: type.subst(s),
|
228
|
+
optional: optional
|
202
229
|
)
|
203
230
|
end
|
204
231
|
|
205
232
|
def free_variables
|
206
|
-
|
233
|
+
type.free_variables
|
207
234
|
end
|
208
235
|
|
209
236
|
def to_s
|
210
|
-
"{ #{params} -> #{return_type} }"
|
237
|
+
"#{optional? ? "?" : ""}{ #{type.params} -> #{type.return_type} }"
|
211
238
|
end
|
212
239
|
end
|
213
240
|
|
@@ -257,8 +284,8 @@ module Steep
|
|
257
284
|
if block_given?
|
258
285
|
params.each_type(&block)
|
259
286
|
self.block&.tap do
|
260
|
-
self.block.params.each_type(&block)
|
261
|
-
yield(self.block.return_type)
|
287
|
+
self.block.type.params.each_type(&block)
|
288
|
+
yield(self.block.type.return_type)
|
262
289
|
end
|
263
290
|
yield(return_type)
|
264
291
|
else
|