steep 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|