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
@@ -34,6 +34,23 @@ module Steep
|
|
34
34
|
def boolean?(type)
|
35
35
|
type.is_a?(AST::Types::Boolean)
|
36
36
|
end
|
37
|
+
|
38
|
+
def optional(type)
|
39
|
+
AST::Types::Union.build(types: [type, nil_instance])
|
40
|
+
end
|
41
|
+
|
42
|
+
def hash_instance?(type)
|
43
|
+
case type
|
44
|
+
when AST::Types::Name
|
45
|
+
type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Hash", absolute: true)
|
46
|
+
else
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def array_instance?(type)
|
52
|
+
type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Array", absolute: true)
|
53
|
+
end
|
37
54
|
end
|
38
55
|
|
39
56
|
class MethodContext
|
@@ -122,8 +139,23 @@ module Steep
|
|
122
139
|
@type_env = type_env
|
123
140
|
end
|
124
141
|
|
142
|
+
def with_new_typing(typing)
|
143
|
+
self.class.new(
|
144
|
+
checker: checker,
|
145
|
+
source: source,
|
146
|
+
annotations: annotations,
|
147
|
+
type_env: type_env,
|
148
|
+
typing: typing,
|
149
|
+
self_type: self_type,
|
150
|
+
method_context: method_context,
|
151
|
+
block_context: block_context,
|
152
|
+
module_context: module_context,
|
153
|
+
break_context: break_context
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
125
157
|
def for_new_method(method_name, node, args:, self_type:)
|
126
|
-
annots = source.annotations(block: node)
|
158
|
+
annots = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
|
127
159
|
type_env = TypeInference::TypeEnv.new(subtyping: checker,
|
128
160
|
const_env: module_context&.const_env || self.type_env.const_env)
|
129
161
|
|
@@ -131,26 +163,61 @@ module Steep
|
|
131
163
|
type_env.set(const: name, type: type)
|
132
164
|
end
|
133
165
|
|
134
|
-
self_type = annots.self_type || self_type
|
166
|
+
self_type = expand_alias(annots.self_type || self_type)
|
135
167
|
|
136
168
|
self_interface = self_type && (self_type != Types.any || nil) && checker.resolve(self_type, with_initialize: true)
|
137
|
-
interface_method = self_interface&.yield_self
|
138
|
-
|
169
|
+
interface_method = self_interface&.yield_self do |interface|
|
170
|
+
interface.methods[method_name]&.yield_self do |method|
|
171
|
+
if self_type.is_a?(AST::Types::Name) && method.type_name == self_type.name
|
172
|
+
method
|
173
|
+
else
|
174
|
+
Interface::Method.new(type_name: self_type,
|
175
|
+
name: method_name,
|
176
|
+
types: method.types,
|
177
|
+
super_method: method,
|
178
|
+
attributes: [])
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
annotation_method = annotations.method_type(method_name)&.yield_self do |method_type|
|
184
|
+
subst = Interface::Substitution.build([],
|
185
|
+
instance_type: module_context&.instance_type || AST::Types::Instance.new,
|
186
|
+
module_type: module_context&.module_type || AST::Types::Class.new,
|
187
|
+
self_type: self_type)
|
139
188
|
Interface::Method.new(type_name: nil,
|
140
189
|
name: method_name,
|
141
|
-
types: [
|
142
|
-
current: current_namespace)],
|
190
|
+
types: [method_type.subst(subst)],
|
143
191
|
super_method: interface_method&.super_method,
|
144
192
|
attributes: [])
|
145
193
|
end
|
146
194
|
|
147
195
|
if interface_method && annotation_method
|
196
|
+
interface_types = interface_method.types.map do |method_type|
|
197
|
+
subst = Interface::Substitution.build(method_type.type_params)
|
198
|
+
method_type.instantiate(subst)
|
199
|
+
end
|
200
|
+
|
201
|
+
unknowns = []
|
202
|
+
annotation_types = annotation_method.types.each.with_object([]) do |method_type, array|
|
203
|
+
fresh = method_type.type_params.map {|var| AST::Types::Var.fresh(var) }
|
204
|
+
unknowns.push(*fresh)
|
205
|
+
|
206
|
+
subst = Interface::Substitution.build(method_type.type_params, fresh)
|
207
|
+
array << method_type.instantiate(subst)
|
208
|
+
end
|
209
|
+
|
210
|
+
constraints = Subtyping::Constraints.new(unknowns: unknowns)
|
211
|
+
interface_types.each do |type|
|
212
|
+
constraints.add_var *type.free_variables.to_a
|
213
|
+
end
|
214
|
+
|
148
215
|
result = checker.check_method(method_name,
|
149
|
-
annotation_method,
|
150
|
-
interface_method,
|
216
|
+
annotation_method.with_types(annotation_types),
|
217
|
+
interface_method.with_types(interface_types),
|
151
218
|
assumption: Set.new,
|
152
219
|
trace: Subtyping::Trace.new,
|
153
|
-
constraints:
|
220
|
+
constraints: constraints)
|
154
221
|
|
155
222
|
if result.failure?
|
156
223
|
typing.add_error Errors::IncompatibleMethodTypeAnnotation.new(
|
@@ -168,10 +235,22 @@ module Steep
|
|
168
235
|
when method && method.types.size == 1
|
169
236
|
method_type = method.types.first
|
170
237
|
return_type = method_type.return_type
|
171
|
-
var_types = TypeConstruction.parameter_types(args, method_type)
|
238
|
+
var_types = TypeConstruction.parameter_types(args, method_type)
|
172
239
|
unless TypeConstruction.valid_parameter_env?(var_types, args.reject {|arg| arg.type == :blockarg }, method_type.params)
|
173
240
|
typing.add_error Errors::MethodArityMismatch.new(node: node)
|
174
241
|
end
|
242
|
+
|
243
|
+
if (block_arg = args.find {|arg| arg.type == :blockarg })
|
244
|
+
if method_type.block
|
245
|
+
block_type = if method_type.block.optional?
|
246
|
+
AST::Types::Union.build(types: [method_type.block.type, Types.nil_instance])
|
247
|
+
else
|
248
|
+
method_type.block.type
|
249
|
+
end
|
250
|
+
var_types[block_arg.children[0].name] = block_type
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
175
254
|
when method
|
176
255
|
typing.add_error Errors::MethodDefinitionWithOverloading.new(node: node, method: method)
|
177
256
|
return_type = union_type(*method.types.map(&:return_type))
|
@@ -214,9 +293,9 @@ module Steep
|
|
214
293
|
end
|
215
294
|
|
216
295
|
type_env = type_env.with_annotations(
|
217
|
-
lvar_types: annots.
|
296
|
+
lvar_types: annots.lvar_types,
|
218
297
|
ivar_types: annots.ivar_types,
|
219
|
-
const_types: annots.const_types
|
298
|
+
const_types: annots.const_types,
|
220
299
|
)
|
221
300
|
|
222
301
|
self.class.new(
|
@@ -234,23 +313,33 @@ module Steep
|
|
234
313
|
end
|
235
314
|
|
236
315
|
def for_module(node)
|
237
|
-
annots = source.annotations(block: node)
|
238
316
|
new_module_name = ModuleName.from_node(node.children.first) or raise "Unexpected module name: #{node.children.first}"
|
317
|
+
new_namespace = nested_namespace(new_module_name)
|
239
318
|
|
319
|
+
annots = source.annotations(block: node, builder: checker.builder, current_module: new_namespace)
|
240
320
|
module_type = AST::Types::Name.new_instance(name: "::Module")
|
241
321
|
|
242
|
-
implement_module_name =
|
243
|
-
if annots.
|
244
|
-
|
322
|
+
implement_module_name = yield_self do
|
323
|
+
if (annotation = annots.implement_module_annotation)
|
324
|
+
absolute_name(annotation.name.name).yield_self do |absolute_name|
|
325
|
+
if checker.builder.signatures.module_name?(absolute_name)
|
326
|
+
AST::Annotation::Implements::Module.new(name: absolute_name,
|
327
|
+
args: annotation.name.args)
|
328
|
+
else
|
329
|
+
Steep.logger.error "Unknown module name given to @implements: #{annotation.name.name}"
|
330
|
+
nil
|
331
|
+
end
|
332
|
+
end
|
245
333
|
else
|
246
|
-
absolute_name(new_module_name).yield_self do |
|
247
|
-
if checker.builder.signatures.module_name?(
|
248
|
-
signature = checker.builder.signatures.find_module(
|
249
|
-
AST::Annotation::Implements::Module.new(name:
|
334
|
+
absolute_name(new_module_name).yield_self do |absolute_name|
|
335
|
+
if checker.builder.signatures.module_name?(absolute_name)
|
336
|
+
signature = checker.builder.signatures.find_module(absolute_name)
|
337
|
+
AST::Annotation::Implements::Module.new(name: absolute_name,
|
250
338
|
args: signature.params&.variables || [])
|
251
339
|
end
|
252
340
|
end
|
253
341
|
end
|
342
|
+
end
|
254
343
|
|
255
344
|
if implement_module_name
|
256
345
|
module_name = implement_module_name.name
|
@@ -258,9 +347,7 @@ module Steep
|
|
258
347
|
|
259
348
|
abstract = checker.builder.build(TypeName::Instance.new(name: module_name))
|
260
349
|
|
261
|
-
instance_type =
|
262
|
-
AST::Types::Name.new_instance(name: module_name, args: module_args)
|
263
|
-
)
|
350
|
+
instance_type = AST::Types::Name.new_instance(name: module_name, args: module_args)
|
264
351
|
|
265
352
|
unless abstract.supers.empty?
|
266
353
|
instance_type = AST::Types::Intersection.build(
|
@@ -275,19 +362,18 @@ module Steep
|
|
275
362
|
end
|
276
363
|
|
277
364
|
if annots.instance_type
|
278
|
-
instance_type =
|
365
|
+
instance_type = annots.instance_type
|
279
366
|
end
|
280
367
|
|
281
368
|
if annots.module_type
|
282
|
-
module_type =
|
369
|
+
module_type = annots.module_type
|
283
370
|
end
|
284
371
|
|
285
|
-
new_namespace = nested_namespace(new_module_name)
|
286
372
|
module_const_env = TypeInference::ConstantEnv.new(builder: checker.builder, current_namespace: new_namespace)
|
287
373
|
|
288
374
|
module_context_ = ModuleContext.new(
|
289
375
|
instance_type: instance_type,
|
290
|
-
module_type: module_type,
|
376
|
+
module_type: annots.self_type || module_type,
|
291
377
|
implement_name: implement_module_name,
|
292
378
|
current_namespace: new_namespace,
|
293
379
|
const_env: module_const_env
|
@@ -313,21 +399,32 @@ module Steep
|
|
313
399
|
end
|
314
400
|
|
315
401
|
def for_class(node)
|
316
|
-
annots = source.annotations(block: node)
|
317
402
|
new_class_name = ModuleName.from_node(node.children.first) or raise "Unexpected class name: #{node.children.first}"
|
403
|
+
new_namespace = nested_namespace(new_class_name)
|
318
404
|
|
319
|
-
|
320
|
-
|
321
|
-
|
405
|
+
annots = source.annotations(block: node, builder: checker.builder, current_module: new_namespace)
|
406
|
+
|
407
|
+
implement_module_name = yield_self do
|
408
|
+
if (annotation = annots.implement_module_annotation)
|
409
|
+
absolute_name(annotation.name.name).yield_self do |absolute_name|
|
410
|
+
if checker.builder.signatures.class_name?(absolute_name)
|
411
|
+
AST::Annotation::Implements::Module.new(name: absolute_name,
|
412
|
+
args: annotation.name.args)
|
413
|
+
else
|
414
|
+
Steep.logger.error "Unknown class name given to @implements: #{annotation.name.name}"
|
415
|
+
nil
|
416
|
+
end
|
417
|
+
end
|
322
418
|
else
|
323
|
-
absolute_name(new_class_name).yield_self do |
|
324
|
-
if checker.builder.signatures.class_name?(
|
325
|
-
signature = checker.builder.signatures.find_class(
|
326
|
-
AST::Annotation::Implements::Module.new(name:
|
419
|
+
absolute_name(new_class_name).yield_self do |absolute_name|
|
420
|
+
if checker.builder.signatures.class_name?(absolute_name)
|
421
|
+
signature = checker.builder.signatures.find_class(absolute_name)
|
422
|
+
AST::Annotation::Implements::Module.new(name: absolute_name,
|
327
423
|
args: signature.params&.variables || [])
|
328
424
|
end
|
329
425
|
end
|
330
426
|
end
|
427
|
+
end
|
331
428
|
|
332
429
|
if implement_module_name
|
333
430
|
class_name = implement_module_name.name
|
@@ -336,15 +433,14 @@ module Steep
|
|
336
433
|
_ = checker.builder.build(TypeName::Instance.new(name: class_name))
|
337
434
|
|
338
435
|
instance_type = AST::Types::Name.new_instance(name: class_name, args: class_args)
|
339
|
-
module_type = AST::Types::Name.new_class(name: class_name, args: [], constructor:
|
436
|
+
module_type = AST::Types::Name.new_class(name: class_name, args: [], constructor: true)
|
340
437
|
end
|
341
438
|
|
342
|
-
new_namespace = nested_namespace(new_class_name)
|
343
439
|
class_const_env = TypeInference::ConstantEnv.new(builder: checker.builder, current_namespace: new_namespace)
|
344
440
|
|
345
441
|
module_context = ModuleContext.new(
|
346
442
|
instance_type: annots.instance_type || instance_type,
|
347
|
-
module_type: annots.module_type || module_type,
|
443
|
+
module_type: annots.self_type || annots.module_type || module_type,
|
348
444
|
implement_name: implement_module_name,
|
349
445
|
current_namespace: new_namespace,
|
350
446
|
const_env: class_const_env
|
@@ -372,13 +468,13 @@ module Steep
|
|
372
468
|
end
|
373
469
|
|
374
470
|
def for_branch(node, truthy_vars: Set.new, type_case_override: nil)
|
375
|
-
annots = source.annotations(block: node)
|
471
|
+
annots = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
|
376
472
|
|
377
473
|
type_env = self.type_env
|
378
474
|
|
379
475
|
lvar_types = self.type_env.lvar_types.each.with_object({}) do |(var, type), env|
|
380
476
|
if truthy_vars.member?(var)
|
381
|
-
env[var] =
|
477
|
+
env[var] = unwrap(type)
|
382
478
|
else
|
383
479
|
env[var] = type
|
384
480
|
end
|
@@ -399,9 +495,9 @@ module Steep
|
|
399
495
|
end
|
400
496
|
|
401
497
|
type_env = type_env.with_annotations(
|
402
|
-
lvar_types: annots.
|
403
|
-
ivar_types: annots.ivar_types
|
404
|
-
const_types: annots.const_types
|
498
|
+
lvar_types: annots.lvar_types,
|
499
|
+
ivar_types: annots.ivar_types,
|
500
|
+
const_types: annots.const_types,
|
405
501
|
gvar_types: {}
|
406
502
|
) do |var, relation, result|
|
407
503
|
typing.add_error(
|
@@ -438,9 +534,15 @@ module Steep
|
|
438
534
|
case node.type
|
439
535
|
when :begin, :kwbegin
|
440
536
|
yield_self do
|
441
|
-
|
442
|
-
|
443
|
-
|
537
|
+
*mid_nodes, last_node = each_child_node(node).to_a
|
538
|
+
mid_nodes.each do |child|
|
539
|
+
synthesize(child)
|
540
|
+
end
|
541
|
+
if last_node
|
542
|
+
type = synthesize(last_node, hint: hint)
|
543
|
+
else
|
544
|
+
type = Types.nil_instance
|
545
|
+
end
|
444
546
|
|
445
547
|
typing.add_typing(node, type)
|
446
548
|
end
|
@@ -451,9 +553,10 @@ module Steep
|
|
451
553
|
rhs = node.children[1]
|
452
554
|
|
453
555
|
if var.name == :_
|
556
|
+
synthesize(rhs, hint: Types.any)
|
454
557
|
typing.add_typing(node, Types.any)
|
455
558
|
else
|
456
|
-
type_assignment(var, rhs, node)
|
559
|
+
type_assignment(var, rhs, node, hint: hint)
|
457
560
|
end
|
458
561
|
end
|
459
562
|
|
@@ -485,7 +588,7 @@ module Steep
|
|
485
588
|
when :send
|
486
589
|
yield_self do
|
487
590
|
if self_class?(node)
|
488
|
-
module_type = module_context.module_type
|
591
|
+
module_type = expand_alias(module_context.module_type)
|
489
592
|
type = if module_type.is_a?(AST::Types::Name) && module_type.name.is_a?(TypeName::Class)
|
490
593
|
AST::Types::Name.new(name: module_type.name.updated(constructor: method_context.constructor),
|
491
594
|
args: module_type.args)
|
@@ -501,7 +604,7 @@ module Steep
|
|
501
604
|
when :csend
|
502
605
|
yield_self do
|
503
606
|
type = if self_class?(node)
|
504
|
-
module_type = module_context.module_type
|
607
|
+
module_type = expand_alias(module_context.module_type)
|
505
608
|
type = if module_type.is_a?(AST::Types::Name)
|
506
609
|
AST::Types::Name.new(name: module_type.name.updated(constructor: method_context.constructor),
|
507
610
|
args: module_type.args)
|
@@ -622,7 +725,11 @@ module Steep
|
|
622
725
|
when :block
|
623
726
|
yield_self do
|
624
727
|
send_node, params, body = node.children
|
625
|
-
|
728
|
+
if send_node.type == :lambda
|
729
|
+
type_lambda(node, block_params: params, block_body: body, type_hint: hint)
|
730
|
+
else
|
731
|
+
type_send(node, send_node: send_node, block_params: params, block_body: body)
|
732
|
+
end
|
626
733
|
end
|
627
734
|
|
628
735
|
when :def
|
@@ -636,11 +743,11 @@ module Steep
|
|
636
743
|
end
|
637
744
|
|
638
745
|
if node.children[2]
|
639
|
-
return_type = new.method_context&.return_type
|
746
|
+
return_type = expand_alias(new.method_context&.return_type)
|
640
747
|
if return_type && !return_type.is_a?(AST::Types::Void)
|
641
748
|
new.check(node.children[2], return_type) do |_, actual_type, result|
|
642
749
|
typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
|
643
|
-
expected: return_type,
|
750
|
+
expected: new.method_context&.return_type,
|
644
751
|
actual: actual_type,
|
645
752
|
result: result))
|
646
753
|
end
|
@@ -648,7 +755,7 @@ module Steep
|
|
648
755
|
new.synthesize(node.children[2])
|
649
756
|
end
|
650
757
|
else
|
651
|
-
return_type = new.method_context&.return_type
|
758
|
+
return_type = expand_alias(new.method_context&.return_type)
|
652
759
|
if return_type && !return_type.is_a?(AST::Types::Void)
|
653
760
|
result = checker.check(
|
654
761
|
Subtyping::Relation.new(sub_type: Types.nil_instance, super_type: return_type),
|
@@ -656,7 +763,7 @@ module Steep
|
|
656
763
|
)
|
657
764
|
if result.failure?
|
658
765
|
typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
|
659
|
-
expected: return_type,
|
766
|
+
expected: new.method_context&.return_type,
|
660
767
|
actual: Types.nil_instance,
|
661
768
|
result: result))
|
662
769
|
end
|
@@ -681,7 +788,7 @@ module Steep
|
|
681
788
|
end
|
682
789
|
|
683
790
|
if node.children[3]
|
684
|
-
return_type = new.method_context&.return_type
|
791
|
+
return_type = expand_alias(new.method_context&.return_type)
|
685
792
|
if return_type && !return_type.is_a?(AST::Types::Void)
|
686
793
|
new.check(node.children[3], return_type) do |return_type, actual_type, result|
|
687
794
|
typing.add_error(Errors::MethodBodyTypeMismatch.new(node: node,
|
@@ -716,18 +823,20 @@ module Steep
|
|
716
823
|
Types.array_instance(union_type(*return_types))
|
717
824
|
end
|
718
825
|
|
719
|
-
if
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
826
|
+
if (ret_type = expand_alias(method_context&.return_type))
|
827
|
+
unless ret_type.is_a?(AST::Types::Void)
|
828
|
+
result = checker.check(
|
829
|
+
Subtyping::Relation.new(sub_type: value_type,
|
830
|
+
super_type: ret_type),
|
831
|
+
constraints: Subtyping::Constraints.empty
|
832
|
+
)
|
833
|
+
|
834
|
+
if result.failure?
|
835
|
+
typing.add_error(Errors::ReturnTypeMismatch.new(node: node,
|
836
|
+
expected: method_context&.return_type,
|
837
|
+
actual: value_type,
|
838
|
+
result: result))
|
839
|
+
end
|
731
840
|
end
|
732
841
|
end
|
733
842
|
end
|
@@ -804,7 +913,7 @@ module Steep
|
|
804
913
|
yield_self do
|
805
914
|
var = node.children[0]
|
806
915
|
rhs = node.children[1]
|
807
|
-
type_assignment(var, rhs, node)
|
916
|
+
type_assignment(var, rhs, node, hint: hint)
|
808
917
|
end
|
809
918
|
|
810
919
|
when :restarg
|
@@ -837,7 +946,7 @@ module Steep
|
|
837
946
|
|
838
947
|
when :int
|
839
948
|
yield_self do
|
840
|
-
literal_type = test_literal_type(node.children[0],
|
949
|
+
literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
|
841
950
|
|
842
951
|
if literal_type
|
843
952
|
typing.add_typing(node, literal_type)
|
@@ -848,7 +957,7 @@ module Steep
|
|
848
957
|
|
849
958
|
when :sym
|
850
959
|
yield_self do
|
851
|
-
literal_type = test_literal_type(node.children[0],
|
960
|
+
literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
|
852
961
|
|
853
962
|
if literal_type
|
854
963
|
typing.add_typing(node, literal_type)
|
@@ -859,7 +968,7 @@ module Steep
|
|
859
968
|
|
860
969
|
when :str
|
861
970
|
yield_self do
|
862
|
-
literal_type = test_literal_type(node.children[0],
|
971
|
+
literal_type = expand_alias(hint) {|hint_| test_literal_type(node.children[0], hint_) }
|
863
972
|
|
864
973
|
if literal_type
|
865
974
|
typing.add_typing(node, literal_type)
|
@@ -873,6 +982,11 @@ module Steep
|
|
873
982
|
|
874
983
|
when :hash
|
875
984
|
yield_self do
|
985
|
+
if Types.hash_instance?(hint)
|
986
|
+
key_hint = hint.args[0]
|
987
|
+
value_hint = hint.args[1]
|
988
|
+
end
|
989
|
+
|
876
990
|
key_types = []
|
877
991
|
value_types = []
|
878
992
|
|
@@ -880,18 +994,22 @@ module Steep
|
|
880
994
|
case child.type
|
881
995
|
when :pair
|
882
996
|
key, value = child.children
|
883
|
-
key_types << synthesize(key)
|
884
|
-
|
997
|
+
key_types << synthesize(key).yield_self do |type|
|
998
|
+
select_super_type(type, key_hint)
|
999
|
+
end
|
1000
|
+
value_types << synthesize(value).yield_self do |type|
|
1001
|
+
select_super_type(type, value_hint)
|
1002
|
+
end
|
885
1003
|
when :kwsplat
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
1004
|
+
expand_alias(synthesize(child.children[0])) do |splat_type, original_type|
|
1005
|
+
if splat_type.is_a?(AST::Types::Name) && splat_type.name == TypeName::Instance.new(name: ModuleName.parse("::Hash"))
|
1006
|
+
key_types << splat_type.args[0]
|
1007
|
+
value_types << splat_type.args[1]
|
1008
|
+
else
|
1009
|
+
typing.add_error Errors::UnexpectedSplat.new(node: child, type: original_type)
|
1010
|
+
key_types << Types.any
|
1011
|
+
value_types << Types.any
|
1012
|
+
end
|
895
1013
|
end
|
896
1014
|
else
|
897
1015
|
raise "Unexpected non pair: #{child.inspect}" unless child.type == :pair
|
@@ -901,10 +1019,14 @@ module Steep
|
|
901
1019
|
key_type = key_types.empty? ? Types.any : AST::Types::Union.build(types: key_types)
|
902
1020
|
value_type = value_types.empty? ? Types.any : AST::Types::Union.build(types: value_types)
|
903
1021
|
|
1022
|
+
if key_types.empty? && value_types.empty? && !hint
|
1023
|
+
typing.add_error Errors::FallbackAny.new(node: node)
|
1024
|
+
end
|
1025
|
+
|
904
1026
|
typing.add_typing(node, Types.hash_instance(key_type, value_type))
|
905
1027
|
end
|
906
1028
|
|
907
|
-
when :dstr
|
1029
|
+
when :dstr, :xstr
|
908
1030
|
each_child_node(node) do |child|
|
909
1031
|
synthesize(child)
|
910
1032
|
end
|
@@ -991,7 +1113,7 @@ module Steep
|
|
991
1113
|
if method_context&.method_type
|
992
1114
|
if method_context.block_type
|
993
1115
|
block_type = method_context.block_type
|
994
|
-
block_type.params.flat_unnamed_params.map(&:last).zip(node.children).each do |(type, node)|
|
1116
|
+
block_type.type.params.flat_unnamed_params.map(&:last).zip(node.children).each do |(type, node)|
|
995
1117
|
if node && type
|
996
1118
|
check(node, type) do |_, rhs_type, result|
|
997
1119
|
typing.add_error(Errors::IncompatibleAssignment.new(node: node,
|
@@ -1002,7 +1124,7 @@ module Steep
|
|
1002
1124
|
end
|
1003
1125
|
end
|
1004
1126
|
|
1005
|
-
typing.add_typing(node, block_type.return_type)
|
1127
|
+
typing.add_typing(node, block_type.type.return_type)
|
1006
1128
|
else
|
1007
1129
|
typing.add_error(Errors::UnexpectedYield.new(node: node))
|
1008
1130
|
fallback_to_any node
|
@@ -1015,8 +1137,13 @@ module Steep
|
|
1015
1137
|
yield_self do
|
1016
1138
|
if method_context&.method
|
1017
1139
|
if method_context.super_method
|
1018
|
-
|
1019
|
-
|
1140
|
+
if method_context.method.incompatible?
|
1141
|
+
typing.add_error Errors::IncompatibleZuper.new(node: node, method: method_context.name)
|
1142
|
+
typing.add_typing node, Types.any
|
1143
|
+
else
|
1144
|
+
types = method_context.super_method.types.map(&:return_type)
|
1145
|
+
typing.add_typing(node, union_type(*types))
|
1146
|
+
end
|
1020
1147
|
else
|
1021
1148
|
typing.add_error(Errors::UnexpectedSuper.new(node: node, method: method_context.name))
|
1022
1149
|
fallback_to_any node
|
@@ -1029,35 +1156,48 @@ module Steep
|
|
1029
1156
|
when :array
|
1030
1157
|
yield_self do
|
1031
1158
|
if node.children.empty?
|
1159
|
+
unless hint
|
1160
|
+
typing.add_error Errors::FallbackAny.new(node: node)
|
1161
|
+
end
|
1032
1162
|
typing.add_typing(node, Types.array_instance(Types.any))
|
1033
1163
|
else
|
1034
|
-
is_tuple =
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1164
|
+
is_tuple = nil
|
1165
|
+
|
1166
|
+
expand_alias(hint) do |hint|
|
1167
|
+
is_tuple = hint.is_a?(AST::Types::Tuple)
|
1168
|
+
is_tuple &&= node.children.all? {|child| child.type != :splat }
|
1169
|
+
is_tuple &&= node.children.map.with_index do |child, index|
|
1170
|
+
synthesize(child, hint: hint.types[index])
|
1171
|
+
end.yield_self do |types|
|
1172
|
+
tuple = AST::Types::Tuple.new(types: types)
|
1173
|
+
relation = Subtyping::Relation.new(sub_type: tuple, super_type: hint)
|
1174
|
+
result = checker.check(relation, constraints: Subtyping::Constraints.empty)
|
1175
|
+
result.success?
|
1176
|
+
end
|
1043
1177
|
end
|
1044
1178
|
|
1045
1179
|
if is_tuple
|
1046
1180
|
array_type = hint
|
1047
1181
|
else
|
1182
|
+
element_hint = expand_alias(hint) do |hint|
|
1183
|
+
Types.array_instance?(hint) && hint.args[0]
|
1184
|
+
end
|
1185
|
+
|
1048
1186
|
element_types = node.children.flat_map do |e|
|
1049
1187
|
if e.type == :splat
|
1050
1188
|
Steep.logger.info "Typing of splat in array is incompatible with Ruby; it does not use #to_a method"
|
1051
1189
|
synthesize(e.children.first).yield_self do |type|
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1190
|
+
expand_alias(type) do |ty|
|
1191
|
+
case ty
|
1192
|
+
when AST::Types::Union
|
1193
|
+
ty.types
|
1194
|
+
else
|
1195
|
+
[ty]
|
1196
|
+
end
|
1057
1197
|
end
|
1058
1198
|
end.map do |type|
|
1059
1199
|
case
|
1060
|
-
when
|
1200
|
+
when Types.array_instance?(type)
|
1061
1201
|
type.args.first
|
1062
1202
|
when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Range", absolute: true)
|
1063
1203
|
type.args.first
|
@@ -1066,7 +1206,7 @@ module Steep
|
|
1066
1206
|
end
|
1067
1207
|
end
|
1068
1208
|
else
|
1069
|
-
[synthesize(e)]
|
1209
|
+
[select_super_type(synthesize(e), element_hint)]
|
1070
1210
|
end
|
1071
1211
|
end
|
1072
1212
|
array_type = Types.array_instance(AST::Types::Union.build(types: element_types))
|
@@ -1098,9 +1238,11 @@ module Steep
|
|
1098
1238
|
end
|
1099
1239
|
|
1100
1240
|
when :or
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1241
|
+
yield_self do
|
1242
|
+
t1, t2 = each_child_node(node).map {|child| synthesize(child) }
|
1243
|
+
type = union_type(unwrap(t1), t2)
|
1244
|
+
typing.add_typing(node, type)
|
1245
|
+
end
|
1104
1246
|
|
1105
1247
|
when :if
|
1106
1248
|
cond, true_clause, false_clause = node.children
|
@@ -1129,7 +1271,7 @@ module Steep
|
|
1129
1271
|
cond, *whens = node.children
|
1130
1272
|
|
1131
1273
|
if cond
|
1132
|
-
cond_type = synthesize(cond)
|
1274
|
+
cond_type = expand_alias(synthesize(cond))
|
1133
1275
|
if cond_type.is_a?(AST::Types::Union)
|
1134
1276
|
var_names = TypeConstruction.value_variables(cond)
|
1135
1277
|
var_types = cond_type.types.dup
|
@@ -1139,7 +1281,7 @@ module Steep
|
|
1139
1281
|
pairs = whens.each.with_object([]) do |clause, pairs|
|
1140
1282
|
if clause&.type == :when
|
1141
1283
|
test_types = clause.children.take(clause.children.size - 1).map do |child|
|
1142
|
-
synthesize(child, hint: hint)
|
1284
|
+
expand_alias(synthesize(child, hint: hint))
|
1143
1285
|
end
|
1144
1286
|
|
1145
1287
|
if (body = clause.children.last)
|
@@ -1240,6 +1382,7 @@ module Steep
|
|
1240
1382
|
case
|
1241
1383
|
when exn_classes && var_name
|
1242
1384
|
instance_types = exn_types.map do |type|
|
1385
|
+
type = expand_alias(type)
|
1243
1386
|
case
|
1244
1387
|
when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Class)
|
1245
1388
|
type.instance_type
|
@@ -1374,7 +1517,47 @@ module Steep
|
|
1374
1517
|
end
|
1375
1518
|
end
|
1376
1519
|
|
1377
|
-
when :
|
1520
|
+
when :block_pass
|
1521
|
+
yield_self do
|
1522
|
+
value = node.children[0]
|
1523
|
+
|
1524
|
+
if hint.is_a?(AST::Types::Proc) && value.type == :sym
|
1525
|
+
if hint.one_arg?
|
1526
|
+
# Assumes Symbol#to_proc implementation
|
1527
|
+
param_type = hint.params.required[0]
|
1528
|
+
interface = checker.resolve(param_type, with_initialize: false)
|
1529
|
+
method = interface.methods[value.children[0]]
|
1530
|
+
if method
|
1531
|
+
return_types = method.types.flat_map do |method_type|
|
1532
|
+
if method_type.params.each_type.count == 0
|
1533
|
+
[method_type.return_type]
|
1534
|
+
end
|
1535
|
+
end
|
1536
|
+
|
1537
|
+
if return_types.any?
|
1538
|
+
type = AST::Types::Proc.new(params: Interface::Params.empty.update(required: [param_type]),
|
1539
|
+
return_type: AST::Types::Union.build(types: return_types))
|
1540
|
+
end
|
1541
|
+
end
|
1542
|
+
else
|
1543
|
+
Steep.logger.error "Passing multiple args through Symbol#to_proc is not supported yet"
|
1544
|
+
end
|
1545
|
+
end
|
1546
|
+
|
1547
|
+
type ||= synthesize(node.children[0], hint: hint)
|
1548
|
+
typing.add_typing node, type
|
1549
|
+
end
|
1550
|
+
|
1551
|
+
when :blockarg
|
1552
|
+
yield_self do
|
1553
|
+
each_child_node node do |child|
|
1554
|
+
synthesize(child)
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
typing.add_typing node, Types.any
|
1558
|
+
end
|
1559
|
+
|
1560
|
+
when :splat, :sclass
|
1378
1561
|
yield_self do
|
1379
1562
|
Steep.logger.error "Unsupported node #{node.type}"
|
1380
1563
|
|
@@ -1404,11 +1587,12 @@ module Steep
|
|
1404
1587
|
end
|
1405
1588
|
end
|
1406
1589
|
|
1407
|
-
def type_assignment(var, rhs, node)
|
1590
|
+
def type_assignment(var, rhs, node, hint: nil)
|
1408
1591
|
if rhs
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1592
|
+
expand_alias(synthesize(rhs, hint: type_env.lvar_types[var.name] || hint)) do |rhs_type|
|
1593
|
+
node_type = assign_type_to_variable(var, rhs_type, node)
|
1594
|
+
typing.add_typing(node, node_type)
|
1595
|
+
end
|
1412
1596
|
else
|
1413
1597
|
raise
|
1414
1598
|
lhs_type = variable_type(var)
|
@@ -1433,7 +1617,7 @@ module Steep
|
|
1433
1617
|
end
|
1434
1618
|
|
1435
1619
|
def type_ivasgn(name, rhs, node)
|
1436
|
-
rhs_type = synthesize(rhs)
|
1620
|
+
rhs_type = synthesize(rhs, hint: type_env.get(ivar: name) { fallback_to_any(node) })
|
1437
1621
|
ivar_type = type_env.assign(ivar: name, type: rhs_type) do |error|
|
1438
1622
|
case error
|
1439
1623
|
when Subtyping::Result::Failure
|
@@ -1451,7 +1635,8 @@ module Steep
|
|
1451
1635
|
|
1452
1636
|
def type_masgn(node)
|
1453
1637
|
lhs, rhs = node.children
|
1454
|
-
|
1638
|
+
rhs_original = synthesize(rhs)
|
1639
|
+
rhs_type = expand_alias(rhs_original)
|
1455
1640
|
|
1456
1641
|
case
|
1457
1642
|
when rhs.type == :array && lhs.children.all? {|a| a.type == :lvasgn || a.type == :ivasgn } && lhs.children.size == rhs.children.size
|
@@ -1564,12 +1749,32 @@ module Steep
|
|
1564
1749
|
end
|
1565
1750
|
end
|
1566
1751
|
|
1752
|
+
def type_lambda(node, block_params:, block_body:, type_hint:)
|
1753
|
+
block_annotations = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
|
1754
|
+
params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
1755
|
+
|
1756
|
+
case type_hint
|
1757
|
+
when AST::Types::Proc
|
1758
|
+
params_hint = type_hint.params
|
1759
|
+
return_hint = type_hint.return_type
|
1760
|
+
end
|
1761
|
+
|
1762
|
+
block_type = type_block(block_param_hint: params_hint,
|
1763
|
+
block_type_hint: return_hint,
|
1764
|
+
node_type_hint: nil,
|
1765
|
+
block_params: params,
|
1766
|
+
block_body: block_body,
|
1767
|
+
block_annotations: block_annotations)
|
1768
|
+
|
1769
|
+
typing.add_typing node, block_type
|
1770
|
+
end
|
1771
|
+
|
1567
1772
|
def type_send(node, send_node:, block_params:, block_body:, unwrap: false)
|
1568
1773
|
receiver, method_name, *arguments = send_node.children
|
1569
1774
|
receiver_type = receiver ? synthesize(receiver) : self_type
|
1570
1775
|
|
1571
1776
|
if unwrap
|
1572
|
-
receiver_type =
|
1777
|
+
receiver_type = unwrap(receiver_type)
|
1573
1778
|
end
|
1574
1779
|
|
1575
1780
|
case receiver_type
|
@@ -1624,7 +1829,7 @@ module Steep
|
|
1624
1829
|
|
1625
1830
|
if block_body && block_params
|
1626
1831
|
unless typing.has_type?(block_body)
|
1627
|
-
block_annotations = source.annotations(block: node)
|
1832
|
+
block_annotations = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
|
1628
1833
|
params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
1629
1834
|
pairs = params.each.map {|param| [param, Types.any] }
|
1630
1835
|
|
@@ -1643,45 +1848,45 @@ module Steep
|
|
1643
1848
|
block_type_env = type_env.dup.yield_self do |env|
|
1644
1849
|
param_pairs.each do |param, type|
|
1645
1850
|
if param.type
|
1646
|
-
env.set(lvar: param.var.name, type:
|
1851
|
+
env.set(lvar: param.var.name, type: param.type)
|
1647
1852
|
else
|
1648
|
-
env.set(lvar: param.var.name, type:
|
1853
|
+
env.set(lvar: param.var.name, type: type)
|
1649
1854
|
end
|
1650
1855
|
end
|
1651
1856
|
|
1652
1857
|
env.with_annotations(
|
1653
|
-
lvar_types: block_annotations.
|
1654
|
-
ivar_types: block_annotations.ivar_types
|
1655
|
-
const_types: block_annotations.const_types
|
1858
|
+
lvar_types: block_annotations.lvar_types,
|
1859
|
+
ivar_types: block_annotations.ivar_types,
|
1860
|
+
const_types: block_annotations.const_types,
|
1656
1861
|
)
|
1657
1862
|
end
|
1658
1863
|
|
1659
1864
|
return_type = if block_annotations.break_type
|
1660
|
-
union_type(method_return_type,
|
1865
|
+
union_type(method_return_type, block_annotations.break_type)
|
1661
1866
|
else
|
1662
1867
|
method_return_type
|
1663
1868
|
end
|
1664
1869
|
Steep.logger.debug("return_type = #{return_type}")
|
1665
1870
|
|
1666
|
-
block_context = BlockContext.new(body_type:
|
1871
|
+
block_context = BlockContext.new(body_type: block_annotations.block_type)
|
1667
1872
|
Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
|
1668
1873
|
|
1669
1874
|
break_context = BreakContext.new(
|
1670
|
-
break_type:
|
1671
|
-
next_type:
|
1875
|
+
break_type: block_annotations.break_type || method_return_type,
|
1876
|
+
next_type: block_annotations.block_type
|
1672
1877
|
)
|
1673
|
-
Steep.logger.debug("break_context { type: #{
|
1878
|
+
Steep.logger.debug("break_context { type: #{break_context.break_type} }")
|
1674
1879
|
|
1675
1880
|
[self.class.new(
|
1676
1881
|
checker: checker,
|
1677
1882
|
source: source,
|
1678
|
-
annotations: annotations
|
1883
|
+
annotations: annotations.merge_block_annotations(block_annotations),
|
1679
1884
|
type_env: block_type_env,
|
1680
1885
|
block_context: block_context,
|
1681
1886
|
typing: typing,
|
1682
1887
|
method_context: method_context,
|
1683
1888
|
module_context: module_context,
|
1684
|
-
self_type:
|
1889
|
+
self_type: block_annotations.self_type || self_type,
|
1685
1890
|
break_context: break_context
|
1686
1891
|
), return_type]
|
1687
1892
|
end
|
@@ -1689,203 +1894,291 @@ module Steep
|
|
1689
1894
|
def type_method_call(node, receiver_type:, method:, args:, block_params:, block_body:)
|
1690
1895
|
results = method.types.map do |method_type|
|
1691
1896
|
Steep.logger.tagged method_type.location&.source do
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1897
|
+
child_typing = typing.new_child
|
1898
|
+
arg_pairs = args.zip(method_type.params, method_type.block&.type)
|
1899
|
+
|
1900
|
+
type_or_error = if arg_pairs
|
1901
|
+
self.with_new_typing(child_typing).try_method_type(
|
1902
|
+
node,
|
1903
|
+
receiver_type: receiver_type,
|
1904
|
+
method_type: method_type,
|
1905
|
+
args: args,
|
1906
|
+
arg_pairs: arg_pairs,
|
1907
|
+
block_params: block_params,
|
1908
|
+
block_body: block_body,
|
1909
|
+
child_typing: child_typing
|
1910
|
+
)
|
1911
|
+
else
|
1912
|
+
Steep.logger.debug(node.inspect)
|
1913
|
+
Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
|
1914
|
+
end
|
1915
|
+
|
1916
|
+
[child_typing, type_or_error, method_type]
|
1705
1917
|
end
|
1706
1918
|
end
|
1707
1919
|
|
1708
|
-
if results.
|
1709
|
-
|
1920
|
+
if (success = results.find {|_, type_or_error| !type_or_error.is_a?(Errors::Base) })
|
1921
|
+
child_typing, type, _ = success
|
1922
|
+
child_typing.save!
|
1923
|
+
type
|
1710
1924
|
else
|
1711
|
-
results.
|
1712
|
-
|
1925
|
+
child_typing, error, method_type = results.first
|
1926
|
+
typing.add_error error
|
1927
|
+
child_typing.save!
|
1928
|
+
|
1929
|
+
case method_type.return_type
|
1930
|
+
when AST::Types::Var
|
1931
|
+
Types.any
|
1932
|
+
else
|
1933
|
+
method_type.return_type
|
1713
1934
|
end
|
1714
1935
|
end
|
1715
1936
|
end
|
1716
1937
|
|
1717
|
-
def try_method_type(node, receiver_type:, method_type:, arg_pairs:, block_params:, block_body:)
|
1938
|
+
def try_method_type(node, receiver_type:, method_type:, args:, arg_pairs:, block_params:, block_body:, child_typing:)
|
1718
1939
|
fresh_types = method_type.type_params.map {|x| AST::Types::Var.fresh(x) }
|
1719
1940
|
fresh_vars = Set.new(fresh_types.map(&:name))
|
1720
1941
|
instantiation = Interface::Substitution.build(method_type.type_params, fresh_types)
|
1721
1942
|
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
)
|
1943
|
+
construction = self.class.new(
|
1944
|
+
checker: checker,
|
1945
|
+
source: source,
|
1946
|
+
annotations: annotations,
|
1947
|
+
type_env: type_env,
|
1948
|
+
typing: child_typing,
|
1949
|
+
self_type: self_type,
|
1950
|
+
method_context: method_context,
|
1951
|
+
block_context: block_context,
|
1952
|
+
module_context: module_context,
|
1953
|
+
break_context: break_context
|
1954
|
+
)
|
1735
1955
|
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1956
|
+
method_type.instantiate(instantiation).yield_self do |method_type|
|
1957
|
+
constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
|
1958
|
+
variance = Subtyping::VariableVariance.from_method_type(method_type)
|
1959
|
+
occurence = Subtyping::VariableOccurence.from_method_type(method_type)
|
1740
1960
|
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1961
|
+
arg_pairs.each do |(arg_node, param_type)|
|
1962
|
+
arg_type = if arg_node.type == :splat
|
1963
|
+
type = construction.synthesize(arg_node.children[0])
|
1964
|
+
child_typing.add_typing(arg_node, type)
|
1965
|
+
else
|
1966
|
+
construction.synthesize(arg_node, hint: param_type)
|
1967
|
+
end
|
1748
1968
|
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1969
|
+
relation = Subtyping::Relation.new(
|
1970
|
+
sub_type: arg_type,
|
1971
|
+
super_type: param_type.subst(instantiation)
|
1972
|
+
)
|
1753
1973
|
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
end
|
1974
|
+
checker.check(relation, constraints: constraints).else do |result|
|
1975
|
+
return Errors::ArgumentTypeMismatch.new(
|
1976
|
+
node: arg_node,
|
1977
|
+
receiver_type: receiver_type,
|
1978
|
+
expected: relation.super_type,
|
1979
|
+
actual: relation.sub_type
|
1980
|
+
)
|
1762
1981
|
end
|
1982
|
+
end
|
1763
1983
|
|
1764
|
-
|
1765
|
-
|
1984
|
+
if block_params && method_type.block
|
1985
|
+
block_annotations = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
|
1986
|
+
block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
1987
|
+
block_param_hint = block_params_.params_type(hint: method_type.block.type.params)
|
1766
1988
|
|
1767
|
-
|
1768
|
-
|
1989
|
+
relation = Subtyping::Relation.new(
|
1990
|
+
sub_type: AST::Types::Proc.new(params: block_param_hint, return_type: AST::Types::Any.new),
|
1991
|
+
super_type: method_type.block.type
|
1992
|
+
)
|
1769
1993
|
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1994
|
+
checker.check(relation, constraints: constraints).else do |result|
|
1995
|
+
return Errors::IncompatibleBlockParameters.new(
|
1996
|
+
node: node,
|
1997
|
+
method_type: method_type
|
1998
|
+
)
|
1999
|
+
end
|
2000
|
+
end
|
1776
2001
|
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
2002
|
+
case
|
2003
|
+
when method_type.block && block_params
|
2004
|
+
Steep.logger.debug "block is okay: method_type=#{method_type}"
|
2005
|
+
Steep.logger.debug "Constraints = #{constraints}"
|
2006
|
+
|
2007
|
+
begin
|
2008
|
+
method_type.subst(constraints.solution(checker, variance: variance, variables: occurence.params)).yield_self do |method_type|
|
2009
|
+
block_type = construction.type_block(block_param_hint: method_type.block.type.params,
|
2010
|
+
block_type_hint: method_type.block.type.return_type,
|
2011
|
+
node_type_hint: method_type.return_type,
|
2012
|
+
block_params: block_params_,
|
2013
|
+
block_body: block_body,
|
2014
|
+
block_annotations: block_annotations)
|
2015
|
+
|
2016
|
+
relation = Subtyping::Relation.new(sub_type: block_type.return_type,
|
2017
|
+
super_type: method_type.block.type.return_type)
|
2018
|
+
|
2019
|
+
result = checker.check(relation, constraints: constraints)
|
2020
|
+
|
2021
|
+
case result
|
2022
|
+
when Subtyping::Result::Success
|
2023
|
+
method_type.return_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).yield_self do |ret_type|
|
2024
|
+
if block_annotations.break_type
|
2025
|
+
AST::Types::Union.new(types: [block_annotations.break_type, ret_type])
|
2026
|
+
else
|
2027
|
+
ret_type
|
2028
|
+
end
|
1790
2029
|
end
|
2030
|
+
|
2031
|
+
when Subtyping::Result::Failure
|
2032
|
+
Errors::BlockTypeMismatch.new(node: node,
|
2033
|
+
expected: method_type.block.type,
|
2034
|
+
actual: block_type,
|
2035
|
+
result: result)
|
1791
2036
|
end
|
1792
2037
|
end
|
1793
2038
|
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
2039
|
+
rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
|
2040
|
+
Errors::UnsatisfiableConstraint.new(node: node,
|
2041
|
+
method_type: method_type,
|
2042
|
+
var: exn.var,
|
2043
|
+
sub_type: exn.sub_type,
|
2044
|
+
super_type: exn.super_type,
|
2045
|
+
result: exn.result)
|
2046
|
+
end
|
2047
|
+
|
2048
|
+
when method_type.block && args.block_pass_arg
|
2049
|
+
begin
|
2050
|
+
method_type.subst(constraints.solution(checker, variance: variance, variables: occurence.params)).yield_self do |method_type|
|
2051
|
+
block_type = synthesize(args.block_pass_arg, hint: method_type.block.type)
|
2052
|
+
relation = Subtyping::Relation.new(sub_type: block_type,
|
2053
|
+
super_type: method_type.block.yield_self do |expected_block|
|
2054
|
+
if expected_block.optional?
|
2055
|
+
Types.optional(expected_block.type)
|
2056
|
+
else
|
2057
|
+
expected_block.type
|
2058
|
+
end
|
2059
|
+
end)
|
2060
|
+
result = checker.check(relation, constraints: constraints)
|
2061
|
+
|
2062
|
+
case result
|
2063
|
+
when Subtyping::Result::Success
|
2064
|
+
method_type.return_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars))
|
2065
|
+
|
2066
|
+
when Subtyping::Result::Failure
|
2067
|
+
Errors::BlockTypeMismatch.new(node: node,
|
2068
|
+
expected: method_type.block.type,
|
2069
|
+
actual: block_type,
|
2070
|
+
result: result)
|
1805
2071
|
end
|
1806
2072
|
end
|
2073
|
+
|
2074
|
+
rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
|
2075
|
+
Errors::UnsatisfiableConstraint.new(node: node,
|
2076
|
+
method_type: method_type,
|
2077
|
+
var: exn.var,
|
2078
|
+
sub_type: exn.sub_type,
|
2079
|
+
super_type: exn.super_type,
|
2080
|
+
result: exn.result)
|
1807
2081
|
end
|
1808
2082
|
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
Steep.logger.debug "Constraints = #{constraints}"
|
2083
|
+
when (!method_type.block || method_type.block.optional?) && !block_params && !block_body && !args.block_pass_arg
|
2084
|
+
# OK, without block
|
2085
|
+
method_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).return_type
|
1813
2086
|
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
2087
|
+
when !method_type.block && (block_params || args.block_pass_arg)
|
2088
|
+
Errors::UnexpectedBlockGiven.new(
|
2089
|
+
node: node,
|
2090
|
+
method_type: method_type
|
2091
|
+
)
|
1817
2092
|
|
1818
|
-
|
1819
|
-
|
1820
|
-
|
2093
|
+
when method_type.block && !method_type.block.optional? && !block_params && !block_body && !args.block_pass_arg
|
2094
|
+
Errors::RequiredBlockMissing.new(
|
2095
|
+
node: node,
|
2096
|
+
method_type: method_type
|
2097
|
+
)
|
1821
2098
|
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
2099
|
+
else
|
2100
|
+
raise "Unexpected case condition"
|
2101
|
+
end
|
2102
|
+
end
|
2103
|
+
end
|
1826
2104
|
|
1827
|
-
|
1828
|
-
|
1829
|
-
end
|
2105
|
+
def type_block(block_param_hint:, block_type_hint:, node_type_hint:, block_params:, block_body:, block_annotations:)
|
2106
|
+
block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
|
1830
2107
|
|
1831
|
-
|
2108
|
+
param_types_hash = {}
|
2109
|
+
if block_param_pairs
|
2110
|
+
block_param_pairs.each do |param, type|
|
2111
|
+
var_name = param.var.name
|
2112
|
+
param_types_hash[var_name] = type
|
2113
|
+
end
|
2114
|
+
else
|
2115
|
+
block_params.each do |param|
|
2116
|
+
var_name = param.var.name
|
2117
|
+
param_types_hash[var_name] = param.type || Types.any
|
2118
|
+
end
|
2119
|
+
end
|
1832
2120
|
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
2121
|
+
block_type_env = type_env.dup.tap do |env|
|
2122
|
+
param_types_hash.each do |name, type|
|
2123
|
+
env.set(lvar: name, type: type)
|
2124
|
+
end
|
2125
|
+
|
2126
|
+
block_annotations.lvar_types.each do |name, type|
|
2127
|
+
env.set(lvar: name, type: type)
|
2128
|
+
end
|
2129
|
+
end
|
1838
2130
|
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
2131
|
+
break_type = if block_annotations.break_type
|
2132
|
+
union_type(node_type_hint, block_annotations.break_type)
|
2133
|
+
else
|
2134
|
+
node_type_hint
|
1842
2135
|
end
|
1843
|
-
|
1844
|
-
typing.add_error Errors::BlockTypeMismatch.new(node: node,
|
1845
|
-
expected: method_type.block.return_type,
|
1846
|
-
actual: block_annotations.block_type || block_body_type,
|
1847
|
-
result: result)
|
1848
|
-
return_type
|
1849
|
-
end
|
1850
|
-
else
|
1851
|
-
child_typing.save!
|
1852
|
-
return_type
|
1853
|
-
end
|
1854
|
-
end
|
2136
|
+
Steep.logger.debug("return_type = #{break_type}")
|
1855
2137
|
|
1856
|
-
|
1857
|
-
|
1858
|
-
method_type: method_type,
|
1859
|
-
var: exn.var,
|
1860
|
-
sub_type: exn.sub_type,
|
1861
|
-
super_type: exn.super_type,
|
1862
|
-
result: exn.result
|
1863
|
-
)
|
1864
|
-
fallback_any_rec node
|
1865
|
-
end
|
2138
|
+
block_context = BlockContext.new(body_type: block_annotations.block_type)
|
2139
|
+
Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
|
1866
2140
|
|
1867
|
-
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
|
2141
|
+
break_context = BreakContext.new(
|
2142
|
+
break_type: break_type,
|
2143
|
+
next_type: block_context.body_type
|
2144
|
+
)
|
2145
|
+
Steep.logger.debug("break_context { type: #{break_context.break_type} }")
|
1872
2146
|
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
2147
|
+
for_block_body = self.class.new(
|
2148
|
+
checker: checker,
|
2149
|
+
source: source,
|
2150
|
+
annotations: annotations.merge_block_annotations(block_annotations),
|
2151
|
+
type_env: block_type_env,
|
2152
|
+
block_context: block_context,
|
2153
|
+
typing: typing,
|
2154
|
+
method_context: method_context,
|
2155
|
+
module_context: module_context,
|
2156
|
+
self_type: block_annotations.self_type || self_type,
|
2157
|
+
break_context: break_context
|
2158
|
+
)
|
1878
2159
|
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
2160
|
+
if block_body
|
2161
|
+
return_type = if (body_type = block_context.body_type)
|
2162
|
+
for_block_body.check(block_body, body_type) do |expected, actual, result|
|
2163
|
+
typing.add_error Errors::BlockTypeMismatch.new(node: block_body,
|
2164
|
+
expected: expected,
|
2165
|
+
actual: actual,
|
2166
|
+
result: result)
|
1884
2167
|
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
2168
|
+
end
|
2169
|
+
body_type
|
2170
|
+
else
|
2171
|
+
for_block_body.synthesize(block_body, hint: block_type_hint)
|
2172
|
+
end
|
2173
|
+
else
|
2174
|
+
return_type = Types.any
|
2175
|
+
end
|
2176
|
+
|
2177
|
+
AST::Types::Proc.new(
|
2178
|
+
params: block_param_hint || block_params.params_type,
|
2179
|
+
return_type: return_type
|
2180
|
+
).tap do |type|
|
2181
|
+
Steep.logger.debug "block_type == #{type}"
|
1889
2182
|
end
|
1890
2183
|
end
|
1891
2184
|
|
@@ -2137,7 +2430,7 @@ module Steep
|
|
2137
2430
|
case
|
2138
2431
|
when module_context.defined_instance_methods.include?(method_name)
|
2139
2432
|
# ok
|
2140
|
-
when annotations.
|
2433
|
+
when annotations.instance_dynamics.include?(method_name)
|
2141
2434
|
# ok
|
2142
2435
|
else
|
2143
2436
|
typing.add_error Errors::MethodDefinitionMissing.new(node: node,
|
@@ -2150,7 +2443,7 @@ module Steep
|
|
2150
2443
|
case
|
2151
2444
|
when module_context.defined_module_methods.include?(method_name)
|
2152
2445
|
# ok
|
2153
|
-
when annotations.
|
2446
|
+
when annotations.module_dynamics.include?(method_name)
|
2154
2447
|
# ok
|
2155
2448
|
else
|
2156
2449
|
typing.add_error Errors::MethodDefinitionMissing.new(node: node,
|
@@ -2160,13 +2453,15 @@ module Steep
|
|
2160
2453
|
end
|
2161
2454
|
end
|
2162
2455
|
|
2163
|
-
annotations.
|
2164
|
-
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2456
|
+
annotations.instance_dynamics.each do |method_name|
|
2457
|
+
unless expected_instance_method_names.member?(method_name)
|
2458
|
+
typing.add_error Errors::UnexpectedDynamicMethod.new(node: node,
|
2459
|
+
module_name: module_name.name,
|
2460
|
+
method_name: method_name)
|
2461
|
+
end
|
2462
|
+
end
|
2463
|
+
annotations.module_dynamics.each do |method_name|
|
2464
|
+
unless expected_module_method_names.member?(method_name)
|
2170
2465
|
typing.add_error Errors::UnexpectedDynamicMethod.new(node: node,
|
2171
2466
|
module_name: module_name.name,
|
2172
2467
|
method_name: method_name)
|
@@ -2234,13 +2529,15 @@ module Steep
|
|
2234
2529
|
typing.type_of(node: node)
|
2235
2530
|
end
|
2236
2531
|
|
2237
|
-
def
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
|
2242
|
-
|
2243
|
-
|
2532
|
+
def unwrap(type)
|
2533
|
+
expand_alias(type) do |expanded|
|
2534
|
+
case
|
2535
|
+
when expanded.is_a?(AST::Types::Union)
|
2536
|
+
types = expanded.types.reject {|type| type.is_a?(AST::Types::Nil) }
|
2537
|
+
AST::Types::Union.build(types: types)
|
2538
|
+
else
|
2539
|
+
type
|
2540
|
+
end
|
2244
2541
|
end
|
2245
2542
|
end
|
2246
2543
|
|
@@ -2272,6 +2569,18 @@ module Steep
|
|
2272
2569
|
end
|
2273
2570
|
end
|
2274
2571
|
|
2572
|
+
def expand_alias(type)
|
2573
|
+
if type
|
2574
|
+
expanded = checker.expand_alias(type)
|
2575
|
+
end
|
2576
|
+
|
2577
|
+
if block_given?
|
2578
|
+
yield expanded, type
|
2579
|
+
else
|
2580
|
+
expanded
|
2581
|
+
end
|
2582
|
+
end
|
2583
|
+
|
2275
2584
|
def test_literal_type(literal, hint)
|
2276
2585
|
case hint
|
2277
2586
|
when AST::Types::Literal
|
@@ -2284,5 +2593,26 @@ module Steep
|
|
2284
2593
|
end
|
2285
2594
|
end
|
2286
2595
|
end
|
2596
|
+
|
2597
|
+
def select_super_type(sub_type, super_type)
|
2598
|
+
if super_type
|
2599
|
+
result = checker.check(
|
2600
|
+
Subtyping::Relation.new(sub_type: sub_type, super_type: super_type),
|
2601
|
+
constraints: Subtyping::Constraints.empty
|
2602
|
+
)
|
2603
|
+
|
2604
|
+
if result.success?
|
2605
|
+
super_type
|
2606
|
+
else
|
2607
|
+
if block_given?
|
2608
|
+
yield result
|
2609
|
+
else
|
2610
|
+
sub_type
|
2611
|
+
end
|
2612
|
+
end
|
2613
|
+
else
|
2614
|
+
sub_type
|
2615
|
+
end
|
2616
|
+
end
|
2287
2617
|
end
|
2288
2618
|
end
|