steep 0.47.1 → 0.48.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 +9 -0
- data/Gemfile.lock +6 -6
- data/lib/steep/ast/types/factory.rb +161 -137
- data/lib/steep/ast/types/var.rb +14 -3
- data/lib/steep/diagnostic/ruby.rb +23 -11
- data/lib/steep/diagnostic/signature.rb +56 -0
- data/lib/steep/interface/method_type.rb +14 -26
- data/lib/steep/interface/type_param.rb +103 -0
- data/lib/steep/server/base_worker.rb +1 -0
- data/lib/steep/server/interaction_worker.rb +1 -1
- data/lib/steep/server/type_check_worker.rb +2 -2
- data/lib/steep/services/signature_service.rb +2 -2
- data/lib/steep/services/type_check_service.rb +2 -1
- data/lib/steep/signature/validator.rb +221 -49
- data/lib/steep/subtyping/cache.rb +30 -0
- data/lib/steep/subtyping/check.rb +582 -708
- data/lib/steep/subtyping/constraints.rb +66 -30
- data/lib/steep/subtyping/relation.rb +60 -0
- data/lib/steep/subtyping/result.rb +190 -16
- data/lib/steep/type_construction.rb +492 -371
- data/lib/steep/type_inference/context.rb +37 -3
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +3 -3
- data/sample/lib/length.rb +35 -0
- data/sample/sig/length.rbs +34 -0
- data/smoke/diagnostics-rbs/nonregular-type-alias.rbs +3 -0
- data/smoke/diagnostics-rbs/recursive-type-alias.rbs +3 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +57 -12
- data/steep.gemspec +1 -1
- metadata +13 -10
- data/lib/steep/drivers/trace_printer.rb +0 -29
- data/lib/steep/interface/method.rb +0 -78
- data/lib/steep/subtyping/trace.rb +0 -71
@@ -63,6 +63,10 @@ module Steep
|
|
63
63
|
context.type_env
|
64
64
|
end
|
65
65
|
|
66
|
+
def variable_context
|
67
|
+
context.variable_context
|
68
|
+
end
|
69
|
+
|
66
70
|
def initialize(checker:, source:, annotations:, typing:, context:)
|
67
71
|
@checker = checker
|
68
72
|
@source = source
|
@@ -114,13 +118,15 @@ module Steep
|
|
114
118
|
def check_relation(sub_type:, super_type:, constraints: Subtyping::Constraints.empty)
|
115
119
|
Steep.logger.debug { "check_relation: self:#{self_type}, instance:#{module_context.instance_type}, class:#{module_context.module_type} |- #{sub_type} <: #{super_type}" }
|
116
120
|
relation = Subtyping::Relation.new(sub_type: sub_type, super_type: super_type)
|
117
|
-
checker.
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
121
|
+
checker.push_variable_bounds(variable_context.upper_bounds) do
|
122
|
+
checker.check(
|
123
|
+
relation,
|
124
|
+
self_type: self_type,
|
125
|
+
instance_type: module_context.instance_type,
|
126
|
+
class_type: module_context.module_type,
|
127
|
+
constraints: constraints
|
128
|
+
)
|
129
|
+
end
|
124
130
|
end
|
125
131
|
|
126
132
|
def for_new_method(method_name, node, args:, self_type:, definition:)
|
@@ -169,6 +175,12 @@ module Steep
|
|
169
175
|
end
|
170
176
|
end
|
171
177
|
|
178
|
+
if definition && method_type
|
179
|
+
variable_context = TypeInference::Context::TypeVariableContext.new(method_type.type_params, parent_context: self.variable_context)
|
180
|
+
else
|
181
|
+
variable_context = self.variable_context
|
182
|
+
end
|
183
|
+
|
172
184
|
method_context = TypeInference::Context::MethodContext.new(
|
173
185
|
name: method_name,
|
174
186
|
method: definition && definition.methods[method_name],
|
@@ -245,12 +257,20 @@ module Steep
|
|
245
257
|
self_type: annots.self_type || self_type,
|
246
258
|
type_env: type_env,
|
247
259
|
lvar_env: lvar_env,
|
248
|
-
call_context: call_context
|
260
|
+
call_context: call_context,
|
261
|
+
variable_context: variable_context
|
249
262
|
),
|
250
263
|
typing: typing,
|
251
264
|
)
|
252
265
|
end
|
253
266
|
|
267
|
+
def with_method_constr(method_name, node, args:, self_type:, definition:)
|
268
|
+
constr = for_new_method(method_name, node, args: args, self_type: self_type, definition: definition)
|
269
|
+
constr.checker.push_variable_bounds(constr.variable_context.upper_bounds) do
|
270
|
+
yield constr
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
254
274
|
def implement_module(module_name:, super_name: nil, annotations:)
|
255
275
|
if (annotation = annotations.implement_module_annotation)
|
256
276
|
absolute_name(annotation.name.name).yield_self do |absolute_name|
|
@@ -332,7 +352,10 @@ module Steep
|
|
332
352
|
module_context = default_module_context(implement_module_name, const_env: module_const_env, current_namespace: new_namespace)
|
333
353
|
|
334
354
|
unless implement_module_name
|
335
|
-
module_context = module_context.update(
|
355
|
+
module_context = module_context.update(
|
356
|
+
module_type: AST::Builtin::Module.instance_type,
|
357
|
+
instance_type: AST::Builtin::BasicObject.instance_type
|
358
|
+
)
|
336
359
|
end
|
337
360
|
|
338
361
|
if implement_module_name
|
@@ -389,6 +412,21 @@ module Steep
|
|
389
412
|
class_type: module_context.module_type
|
390
413
|
).annotate(annots)
|
391
414
|
|
415
|
+
if implement_module_name
|
416
|
+
definition = checker.factory.definition_builder.build_instance(implement_module_name.name)
|
417
|
+
type_params = definition.type_params_decl.map do |param|
|
418
|
+
Interface::TypeParam.new(
|
419
|
+
name: param.name,
|
420
|
+
upper_bound: checker.factory.type_opt(param.upper_bound),
|
421
|
+
variance: param.variance,
|
422
|
+
unchecked: param.unchecked?
|
423
|
+
)
|
424
|
+
end
|
425
|
+
variable_context = TypeInference::Context::TypeVariableContext.new(type_params)
|
426
|
+
else
|
427
|
+
variable_context = TypeInference::Context::TypeVariableContext.empty
|
428
|
+
end
|
429
|
+
|
392
430
|
self.class.new(
|
393
431
|
checker: checker,
|
394
432
|
source: source,
|
@@ -402,11 +440,19 @@ module Steep
|
|
402
440
|
self_type: module_context.module_type,
|
403
441
|
type_env: module_type_env,
|
404
442
|
lvar_env: lvar_env,
|
405
|
-
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name)
|
443
|
+
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
|
444
|
+
variable_context: variable_context
|
406
445
|
)
|
407
446
|
)
|
408
447
|
end
|
409
448
|
|
449
|
+
def with_module_constr(node)
|
450
|
+
constr = for_module(node)
|
451
|
+
constr.checker.push_variable_bounds(constr.variable_context.upper_bounds) do
|
452
|
+
yield constr
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
410
456
|
def for_class(node)
|
411
457
|
new_class_name = module_name_from_node(node.children.first) or raise "Unexpected class name: #{node.children.first}"
|
412
458
|
super_class_name = node.children[1] && module_name_from_node(node.children[1])
|
@@ -422,10 +468,7 @@ module Steep
|
|
422
468
|
|
423
469
|
if implement_module_name
|
424
470
|
if super_class_name && implement_module_name.name == absolute_name(super_class_name)
|
425
|
-
module_context = module_context.update(
|
426
|
-
instance_definition: nil,
|
427
|
-
module_definition: nil
|
428
|
-
)
|
471
|
+
module_context = module_context.update(instance_definition: nil, module_definition: nil)
|
429
472
|
end
|
430
473
|
else
|
431
474
|
module_context = module_context.update(
|
@@ -446,6 +489,18 @@ module Steep
|
|
446
489
|
module_context = module_context.update(module_type: annots.self_type)
|
447
490
|
end
|
448
491
|
|
492
|
+
definition = checker.factory.definition_builder.build_instance(module_context.class_name)
|
493
|
+
type_params = definition.type_params_decl.map do |type_param|
|
494
|
+
Interface::TypeParam.new(
|
495
|
+
name: type_param.name,
|
496
|
+
upper_bound: type_param.upper_bound&.yield_self {|t| checker.factory.type(t) },
|
497
|
+
variance: type_param.variance,
|
498
|
+
unchecked: type_param.unchecked?,
|
499
|
+
location: type_param.location
|
500
|
+
)
|
501
|
+
end
|
502
|
+
variable_context = TypeInference::Context::TypeVariableContext.new(type_params)
|
503
|
+
|
449
504
|
class_type_env = TypeInference::TypeEnv.build(annotations: annots,
|
450
505
|
subtyping: checker,
|
451
506
|
const_env: class_const_env,
|
@@ -466,7 +521,8 @@ module Steep
|
|
466
521
|
self_type: module_context.module_type,
|
467
522
|
type_env: class_type_env,
|
468
523
|
lvar_env: lvar_env,
|
469
|
-
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name)
|
524
|
+
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
|
525
|
+
variable_context: variable_context
|
470
526
|
)
|
471
527
|
|
472
528
|
self.class.new(
|
@@ -478,6 +534,24 @@ module Steep
|
|
478
534
|
)
|
479
535
|
end
|
480
536
|
|
537
|
+
def with_class_constr(node)
|
538
|
+
constr = for_class(node)
|
539
|
+
|
540
|
+
constr.checker.push_variable_bounds(constr.variable_context.upper_bounds) do
|
541
|
+
yield constr
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
def with_sclass_constr(node, type)
|
546
|
+
if constr = for_sclass(node, type)
|
547
|
+
constr.checker.push_variable_bounds(constr.variable_context.upper_bounds) do
|
548
|
+
yield constr
|
549
|
+
end
|
550
|
+
else
|
551
|
+
yield nil
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
481
555
|
def for_sclass(node, type)
|
482
556
|
annots = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
483
557
|
|
@@ -554,7 +628,8 @@ module Steep
|
|
554
628
|
self_type: module_context.module_type,
|
555
629
|
type_env: type_env,
|
556
630
|
lvar_env: lvar_env,
|
557
|
-
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name)
|
631
|
+
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
|
632
|
+
variable_context: TypeInference::Context::TypeVariableContext.empty # Assuming `::Class` and `::Module` don't have type params
|
558
633
|
)
|
559
634
|
|
560
635
|
self.class.new(
|
@@ -959,75 +1034,76 @@ module Steep
|
|
959
1034
|
yield_self do
|
960
1035
|
name, args_node, body_node = node.children
|
961
1036
|
|
962
|
-
|
1037
|
+
with_method_constr(
|
963
1038
|
name,
|
964
1039
|
node,
|
965
1040
|
args: args_node.children,
|
966
1041
|
self_type: module_context&.instance_type,
|
967
1042
|
definition: module_context&.instance_definition
|
968
|
-
)
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
1043
|
+
) do |new|
|
1044
|
+
new.typing.add_context_for_node(node, context: new.context)
|
1045
|
+
new.typing.add_context_for_body(node, context: new.context)
|
1046
|
+
|
1047
|
+
new.method_context.tap do |method_context|
|
1048
|
+
if method_context.method
|
1049
|
+
method_name = InstanceMethodName.new(type_name: method_context.method.implemented_in, method_name: name)
|
1050
|
+
new.typing.source_index.add_definition(method: method_name, definition: node)
|
1051
|
+
end
|
976
1052
|
end
|
977
|
-
end
|
978
|
-
|
979
|
-
new = new.synthesize_children(args_node)
|
980
1053
|
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
new.
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
1054
|
+
new = new.synthesize_children(args_node)
|
1055
|
+
|
1056
|
+
body_pair = if body_node
|
1057
|
+
return_type = expand_alias(new.method_context&.return_type)
|
1058
|
+
if return_type && !return_type.is_a?(AST::Types::Void)
|
1059
|
+
new.check(body_node, return_type) do |_, actual_type, result|
|
1060
|
+
typing.add_error(
|
1061
|
+
Diagnostic::Ruby::MethodBodyTypeMismatch.new(
|
1062
|
+
node: node,
|
1063
|
+
expected: new.method_context&.return_type,
|
1064
|
+
actual: actual_type,
|
1065
|
+
result: result
|
1066
|
+
)
|
991
1067
|
)
|
992
|
-
|
1068
|
+
end
|
1069
|
+
else
|
1070
|
+
new.synthesize(body_node)
|
993
1071
|
end
|
994
1072
|
else
|
995
|
-
new.
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
actual: AST::Builtin.nil_type,
|
1007
|
-
result: result
|
1073
|
+
return_type = expand_alias(new.method_context&.return_type)
|
1074
|
+
if return_type && !return_type.is_a?(AST::Types::Void)
|
1075
|
+
result = check_relation(sub_type: AST::Builtin.nil_type, super_type: return_type)
|
1076
|
+
if result.failure?
|
1077
|
+
typing.add_error(
|
1078
|
+
Diagnostic::Ruby::MethodBodyTypeMismatch.new(
|
1079
|
+
node: node,
|
1080
|
+
expected: new.method_context&.return_type,
|
1081
|
+
actual: AST::Builtin.nil_type,
|
1082
|
+
result: result
|
1083
|
+
)
|
1008
1084
|
)
|
1009
|
-
|
1085
|
+
end
|
1010
1086
|
end
|
1087
|
+
|
1088
|
+
Pair.new(type: AST::Builtin.nil_type, constr: new)
|
1011
1089
|
end
|
1012
1090
|
|
1013
|
-
|
1014
|
-
|
1091
|
+
if body_node
|
1092
|
+
# Add context to ranges from the end of the method body to the beginning of the `end` keyword
|
1093
|
+
if node.loc.end
|
1094
|
+
# Skip end-less def
|
1095
|
+
begin_pos = body_node.loc.expression.end_pos
|
1096
|
+
end_pos = node.loc.end.begin_pos
|
1097
|
+
typing.add_context(begin_pos..end_pos, context: body_pair.context)
|
1098
|
+
end
|
1099
|
+
end
|
1015
1100
|
|
1016
|
-
|
1017
|
-
|
1018
|
-
if node.loc.end
|
1019
|
-
# Skip end-less def
|
1020
|
-
begin_pos = body_node.loc.expression.end_pos
|
1021
|
-
end_pos = node.loc.end.begin_pos
|
1022
|
-
typing.add_context(begin_pos..end_pos, context: body_pair.context)
|
1101
|
+
if module_context
|
1102
|
+
module_context.defined_instance_methods << node.children[0]
|
1023
1103
|
end
|
1024
|
-
end
|
1025
1104
|
|
1026
|
-
|
1027
|
-
module_context.defined_instance_methods << node.children[0]
|
1105
|
+
add_typing(node, type: AST::Builtin::Symbol.instance_type)
|
1028
1106
|
end
|
1029
|
-
|
1030
|
-
add_typing(node, type: AST::Builtin::Symbol.instance_type)
|
1031
1107
|
end
|
1032
1108
|
|
1033
1109
|
when :defs
|
@@ -1109,12 +1185,14 @@ module Steep
|
|
1109
1185
|
method_return_type = expand_alias(method_context&.return_type)
|
1110
1186
|
|
1111
1187
|
return_types = node.children.map do |value|
|
1112
|
-
synthesize(
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1188
|
+
synthesize(
|
1189
|
+
value,
|
1190
|
+
hint: if method_return_type.is_a?(AST::Types::Void)
|
1191
|
+
nil
|
1192
|
+
else
|
1193
|
+
method_return_type
|
1194
|
+
end
|
1195
|
+
).type
|
1118
1196
|
end
|
1119
1197
|
|
1120
1198
|
value_type = if return_types.size == 1
|
@@ -1427,7 +1505,7 @@ module Steep
|
|
1427
1505
|
end
|
1428
1506
|
_, constr = constr.synthesize(sup) if sup
|
1429
1507
|
|
1430
|
-
|
1508
|
+
with_class_constr(node) do |constructor|
|
1431
1509
|
if module_type = constructor.module_context&.module_type
|
1432
1510
|
_, constructor = constructor.add_typing(name, type: module_type)
|
1433
1511
|
else
|
@@ -1467,7 +1545,7 @@ module Steep
|
|
1467
1545
|
_, constr = constr.synthesize(name)
|
1468
1546
|
end
|
1469
1547
|
|
1470
|
-
|
1548
|
+
with_module_constr(node) do |constructor|
|
1471
1549
|
if module_type = constructor.module_context&.module_type
|
1472
1550
|
_, constructor = constructor.add_typing(name, type: module_type)
|
1473
1551
|
else
|
@@ -1495,27 +1573,28 @@ module Steep
|
|
1495
1573
|
when :sclass
|
1496
1574
|
yield_self do
|
1497
1575
|
type, constr = synthesize(node.children[0])
|
1498
|
-
constructor = constr.for_sclass(node, type)
|
1499
1576
|
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1577
|
+
with_sclass_constr(node, type) do |constructor|
|
1578
|
+
unless constructor
|
1579
|
+
typing.add_error(
|
1580
|
+
Diagnostic::Ruby::UnsupportedSyntax.new(
|
1581
|
+
node: node,
|
1582
|
+
message: "sclass receiver must be instance type or singleton type, but type given `#{type}`"
|
1583
|
+
)
|
1505
1584
|
)
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
end
|
1585
|
+
constr.add_typing(node, type: AST::Builtin.nil_type)
|
1586
|
+
return
|
1587
|
+
end
|
1510
1588
|
|
1511
|
-
|
1512
|
-
|
1589
|
+
constructor.typing.add_context_for_node(node, context: constructor.context)
|
1590
|
+
constructor.typing.add_context_for_body(node, context: constructor.context)
|
1513
1591
|
|
1514
|
-
|
1592
|
+
constructor.synthesize(node.children[1]) if node.children[1]
|
1515
1593
|
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1594
|
+
if constructor.module_context.instance_definition && module_context.module_definition
|
1595
|
+
if constructor.module_context.instance_definition.type_name == module_context.module_definition.type_name
|
1596
|
+
module_context.defined_module_methods.merge(constructor.module_context.defined_instance_methods)
|
1597
|
+
end
|
1519
1598
|
end
|
1520
1599
|
end
|
1521
1600
|
|
@@ -1573,8 +1652,7 @@ module Steep
|
|
1573
1652
|
instance_type: module_context.instance_type,
|
1574
1653
|
class_type: module_context.module_type
|
1575
1654
|
) do |error|
|
1576
|
-
|
1577
|
-
when Subtyping::Result::Failure
|
1655
|
+
if error
|
1578
1656
|
const_type = type_env.get(const: const_name)
|
1579
1657
|
typing.add_error(
|
1580
1658
|
Diagnostic::Ruby::IncompatibleAssignment.new(
|
@@ -1584,7 +1662,7 @@ module Steep
|
|
1584
1662
|
result: error
|
1585
1663
|
)
|
1586
1664
|
)
|
1587
|
-
|
1665
|
+
else
|
1588
1666
|
typing.add_error(
|
1589
1667
|
Diagnostic::Ruby::UnknownConstantAssigned.new(
|
1590
1668
|
node: node,
|
@@ -2385,7 +2463,7 @@ module Steep
|
|
2385
2463
|
raise "#synthesize should return an instance of Pair: #{pair.class}, node=#{node.inspect}"
|
2386
2464
|
end
|
2387
2465
|
end
|
2388
|
-
rescue RBS::
|
2466
|
+
rescue RBS::BaseError => exn
|
2389
2467
|
Steep.logger.warn { "Unexpected RBS error: #{exn.message}" }
|
2390
2468
|
exn.backtrace.each {|loc| Steep.logger.warn " #{loc}" }
|
2391
2469
|
typing.add_error(Diagnostic::Ruby::UnexpectedError.new(node: node, error: exn))
|
@@ -2411,6 +2489,7 @@ module Steep
|
|
2411
2489
|
|
2412
2490
|
def type_ivasgn(name, rhs, node)
|
2413
2491
|
rhs_type = synthesize(rhs, hint: type_env.get(ivar: name) { fallback_to_any(node) }).type
|
2492
|
+
|
2414
2493
|
ivar_type = type_env.assign(
|
2415
2494
|
ivar: name,
|
2416
2495
|
type: rhs_type,
|
@@ -2418,8 +2497,7 @@ module Steep
|
|
2418
2497
|
instance_type: module_context.instance_type,
|
2419
2498
|
class_type: module_context.module_type
|
2420
2499
|
) do |error|
|
2421
|
-
|
2422
|
-
when Subtyping::Result::Failure
|
2500
|
+
if error
|
2423
2501
|
type = type_env.get(ivar: name)
|
2424
2502
|
typing.add_error(
|
2425
2503
|
Diagnostic::Ruby::IncompatibleAssignment.new(
|
@@ -2429,7 +2507,7 @@ module Steep
|
|
2429
2507
|
result: error
|
2430
2508
|
)
|
2431
2509
|
)
|
2432
|
-
|
2510
|
+
else
|
2433
2511
|
fallback_to_any node
|
2434
2512
|
end
|
2435
2513
|
end
|
@@ -2473,8 +2551,7 @@ module Steep
|
|
2473
2551
|
instance_type: module_context.instance_type,
|
2474
2552
|
class_type: module_context.module_type
|
2475
2553
|
) do |error|
|
2476
|
-
|
2477
|
-
when Subtyping::Result::Failure
|
2554
|
+
if error
|
2478
2555
|
var_type = type_env.get(ivar: ivar)
|
2479
2556
|
typing.add_error(
|
2480
2557
|
Diagnostic::Ruby::IncompatibleAssignment.new(
|
@@ -2484,7 +2561,7 @@ module Steep
|
|
2484
2561
|
result: error
|
2485
2562
|
)
|
2486
2563
|
)
|
2487
|
-
|
2564
|
+
else
|
2488
2565
|
fallback_to_any node
|
2489
2566
|
end
|
2490
2567
|
end
|
@@ -2830,6 +2907,32 @@ module Steep
|
|
2830
2907
|
)
|
2831
2908
|
)
|
2832
2909
|
|
2910
|
+
when AST::Types::Var
|
2911
|
+
if upper_bound = variable_context[receiver_type.name]
|
2912
|
+
interface = calculate_interface(upper_bound, private: false)
|
2913
|
+
|
2914
|
+
constr.type_send_interface(
|
2915
|
+
node,
|
2916
|
+
interface: interface,
|
2917
|
+
receiver: receiver,
|
2918
|
+
receiver_type: receiver_type,
|
2919
|
+
method_name: method_name,
|
2920
|
+
arguments: arguments,
|
2921
|
+
block_params: block_params,
|
2922
|
+
block_body: block_body
|
2923
|
+
)
|
2924
|
+
else
|
2925
|
+
constr = constr.synthesize_children(node, skips: [receiver])
|
2926
|
+
constr.add_call(
|
2927
|
+
TypeInference::MethodCall::NoMethodError.new(
|
2928
|
+
node: node,
|
2929
|
+
context: context.method_context,
|
2930
|
+
method_name: method_name,
|
2931
|
+
receiver_type: receiver_type,
|
2932
|
+
error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2933
|
+
)
|
2934
|
+
)
|
2935
|
+
end
|
2833
2936
|
when AST::Types::Void, AST::Types::Bot, AST::Types::Top, AST::Types::Var
|
2834
2937
|
constr = constr.synthesize_children(node, skips: [receiver])
|
2835
2938
|
constr.add_call(
|
@@ -2872,6 +2975,7 @@ module Steep
|
|
2872
2975
|
block_params: block_params,
|
2873
2976
|
block_body: block_body)
|
2874
2977
|
end
|
2978
|
+
|
2875
2979
|
else
|
2876
2980
|
interface = calculate_interface(receiver_type, private: private, self_type: receiver_type)
|
2877
2981
|
|
@@ -2991,115 +3095,161 @@ module Steep
|
|
2991
3095
|
end
|
2992
3096
|
end
|
2993
3097
|
|
3098
|
+
def apply_solution(errors, node:, method_type:)
|
3099
|
+
subst = yield
|
3100
|
+
|
3101
|
+
[
|
3102
|
+
method_type.subst(subst),
|
3103
|
+
true,
|
3104
|
+
subst
|
3105
|
+
]
|
3106
|
+
|
3107
|
+
rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
|
3108
|
+
errors << Diagnostic::Ruby::UnsatisfiableConstraint.new(
|
3109
|
+
node: node,
|
3110
|
+
method_type: method_type,
|
3111
|
+
var: exn.var,
|
3112
|
+
sub_type: exn.sub_type,
|
3113
|
+
super_type: exn.super_type,
|
3114
|
+
result: exn.result
|
3115
|
+
)
|
3116
|
+
[method_type, false, Interface::Substitution.empty]
|
3117
|
+
end
|
3118
|
+
|
3119
|
+
def eliminate_vars(type, variables, to: AST::Builtin.any_type)
|
3120
|
+
if variables.empty?
|
3121
|
+
type
|
3122
|
+
else
|
3123
|
+
subst = Interface::Substitution.build(variables, Array.new(variables.size, to))
|
3124
|
+
type.subst(subst)
|
3125
|
+
end
|
3126
|
+
end
|
3127
|
+
|
2994
3128
|
def try_method_type(node, receiver_type:, method_name:, method_type:, arguments:, block_params:, block_body:, topdown_hint:)
|
2995
|
-
|
2996
|
-
|
2997
|
-
instantiation = Interface::Substitution.build(method_type.type_params, fresh_types)
|
3129
|
+
type_params, instantiation = Interface::TypeParam.rename(method_type.type_params)
|
3130
|
+
type_param_names = type_params.map(&:name)
|
2998
3131
|
|
2999
3132
|
constr = self
|
3000
3133
|
|
3001
3134
|
method_type = method_type.instantiate(instantiation)
|
3002
3135
|
|
3003
|
-
constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
|
3004
3136
|
variance = Subtyping::VariableVariance.from_method_type(method_type)
|
3005
3137
|
occurence = Subtyping::VariableOccurence.from_method_type(method_type)
|
3138
|
+
constraints = Subtyping::Constraints.new(unknowns: type_params.map(&:name))
|
3139
|
+
ccontext = Subtyping::Constraints::Context.new(
|
3140
|
+
self_type: self_type,
|
3141
|
+
instance_type: module_context.instance_type,
|
3142
|
+
class_type: module_context.module_type,
|
3143
|
+
variance: variance
|
3144
|
+
)
|
3006
3145
|
|
3007
|
-
|
3146
|
+
upper_bounds = {}
|
3008
3147
|
|
3009
|
-
|
3010
|
-
|
3011
|
-
|
3012
|
-
|
3013
|
-
|
3014
|
-
|
3015
|
-
type: arg.param.type,
|
3016
|
-
receiver_type: receiver_type,
|
3017
|
-
constraints: constraints,
|
3018
|
-
errors: errors
|
3019
|
-
)
|
3148
|
+
type_params.each do |param|
|
3149
|
+
if ub = param.upper_bound
|
3150
|
+
constraints.add(param.name, super_type: ub, skip: true)
|
3151
|
+
upper_bounds[param.name] = ub
|
3152
|
+
end
|
3153
|
+
end
|
3020
3154
|
|
3021
|
-
|
3022
|
-
|
3023
|
-
|
3024
|
-
|
3025
|
-
|
3155
|
+
checker.push_variable_bounds(upper_bounds) do
|
3156
|
+
errors = []
|
3157
|
+
|
3158
|
+
args = TypeInference::SendArgs.new(node: node, arguments: arguments, method_name: method_name, method_type: method_type)
|
3159
|
+
es = args.each do |arg|
|
3160
|
+
case arg
|
3161
|
+
when TypeInference::SendArgs::PositionalArgs::NodeParamPair
|
3162
|
+
_, constr = constr.type_check_argument(
|
3163
|
+
arg.node,
|
3164
|
+
type: arg.param.type,
|
3026
3165
|
receiver_type: receiver_type,
|
3027
3166
|
constraints: constraints,
|
3028
|
-
report_node: arg.node,
|
3029
3167
|
errors: errors
|
3030
3168
|
)
|
3031
|
-
end
|
3032
3169
|
|
3033
|
-
|
3034
|
-
|
3035
|
-
constr.synthesize(n)
|
3036
|
-
end
|
3037
|
-
|
3038
|
-
when TypeInference::SendArgs::PositionalArgs::SplatArg
|
3039
|
-
arg_type, _ = constr
|
3040
|
-
.with_child_typing(range: arg.node.loc.expression.begin_pos ... arg.node.loc.expression.end_pos)
|
3041
|
-
.try_tuple_type!(arg.node.children[0])
|
3042
|
-
arg.type = arg_type
|
3043
|
-
|
3044
|
-
when TypeInference::SendArgs::PositionalArgs::MissingArg
|
3045
|
-
# ignore
|
3046
|
-
|
3047
|
-
when TypeInference::SendArgs::KeywordArgs::ArgTypePairs
|
3048
|
-
arg.pairs.each do |node, type|
|
3049
|
-
_, constr = bypass_splat(node) do |node|
|
3170
|
+
when TypeInference::SendArgs::PositionalArgs::NodeTypePair
|
3171
|
+
_, constr = bypass_splat(arg.node) do |n|
|
3050
3172
|
constr.type_check_argument(
|
3051
|
-
|
3052
|
-
type:
|
3173
|
+
n,
|
3174
|
+
type: arg.node_type,
|
3053
3175
|
receiver_type: receiver_type,
|
3054
3176
|
constraints: constraints,
|
3177
|
+
report_node: arg.node,
|
3055
3178
|
errors: errors
|
3056
3179
|
)
|
3057
3180
|
end
|
3058
|
-
end
|
3059
3181
|
|
3060
|
-
|
3061
|
-
if arg.node.type == :pair
|
3062
|
-
arg.node.children.each do |nn|
|
3063
|
-
_, constr = constr.synthesize(nn)
|
3064
|
-
end
|
3065
|
-
else
|
3182
|
+
when TypeInference::SendArgs::PositionalArgs::UnexpectedArg
|
3066
3183
|
_, constr = bypass_splat(arg.node) do |n|
|
3067
3184
|
constr.synthesize(n)
|
3068
3185
|
end
|
3069
|
-
end
|
3070
3186
|
|
3071
|
-
|
3072
|
-
|
3073
|
-
|
3074
|
-
|
3187
|
+
when TypeInference::SendArgs::PositionalArgs::SplatArg
|
3188
|
+
arg_type, _ = constr
|
3189
|
+
.with_child_typing(range: arg.node.loc.expression.begin_pos ... arg.node.loc.expression.end_pos)
|
3190
|
+
.try_tuple_type!(arg.node.children[0])
|
3191
|
+
arg.type = arg_type
|
3192
|
+
|
3193
|
+
when TypeInference::SendArgs::PositionalArgs::MissingArg
|
3194
|
+
# ignore
|
3195
|
+
|
3196
|
+
when TypeInference::SendArgs::KeywordArgs::ArgTypePairs
|
3197
|
+
arg.pairs.each do |node, type|
|
3198
|
+
_, constr = bypass_splat(node) do |node|
|
3199
|
+
constr.type_check_argument(
|
3200
|
+
node,
|
3201
|
+
type: type,
|
3202
|
+
receiver_type: receiver_type,
|
3203
|
+
constraints: constraints,
|
3204
|
+
errors: errors
|
3205
|
+
)
|
3206
|
+
end
|
3075
3207
|
end
|
3076
3208
|
|
3077
|
-
|
3078
|
-
|
3209
|
+
when TypeInference::SendArgs::KeywordArgs::UnexpectedKeyword
|
3210
|
+
if arg.node.type == :pair
|
3211
|
+
arg.node.children.each do |nn|
|
3212
|
+
_, constr = constr.synthesize(nn)
|
3213
|
+
end
|
3214
|
+
else
|
3215
|
+
_, constr = bypass_splat(arg.node) do |n|
|
3216
|
+
constr.synthesize(n)
|
3217
|
+
end
|
3218
|
+
end
|
3079
3219
|
|
3080
|
-
|
3220
|
+
when TypeInference::SendArgs::KeywordArgs::SplatArg
|
3221
|
+
type, _ = bypass_splat(arg.node) do |sp_node|
|
3222
|
+
if sp_node.type == :hash
|
3223
|
+
pair = constr.type_hash_record(sp_node, nil) and break pair
|
3224
|
+
end
|
3081
3225
|
|
3082
|
-
|
3083
|
-
|
3084
|
-
else
|
3085
|
-
raise arg.inspect
|
3086
|
-
end
|
3226
|
+
constr.synthesize(sp_node)
|
3227
|
+
end
|
3087
3228
|
|
3088
|
-
|
3089
|
-
|
3229
|
+
arg.type = type
|
3230
|
+
|
3231
|
+
when TypeInference::SendArgs::KeywordArgs::MissingKeyword
|
3232
|
+
# ignore
|
3233
|
+
else
|
3234
|
+
raise arg.inspect
|
3235
|
+
end
|
3236
|
+
|
3237
|
+
constr
|
3238
|
+
end
|
3090
3239
|
|
3091
|
-
|
3240
|
+
errors.push(*es)
|
3092
3241
|
|
3093
|
-
|
3094
|
-
|
3095
|
-
|
3096
|
-
|
3242
|
+
if block_params
|
3243
|
+
# block is given
|
3244
|
+
block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
3245
|
+
block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
3097
3246
|
|
3098
|
-
|
3099
|
-
|
3247
|
+
if method_type.block
|
3248
|
+
# Method accepts block
|
3249
|
+
pairs = method_type.block && block_params_&.zip(method_type.block.type.params)
|
3100
3250
|
|
3101
|
-
|
3102
|
-
|
3251
|
+
if pairs
|
3252
|
+
# Block parameters are compatible with the block type
|
3103
3253
|
block_constr = constr.for_block(
|
3104
3254
|
block_params: block_params_,
|
3105
3255
|
block_param_hint: method_type.block.type.params,
|
@@ -3131,236 +3281,206 @@ module Steep
|
|
3131
3281
|
end
|
3132
3282
|
end
|
3133
3283
|
|
3134
|
-
s =
|
3135
|
-
|
3136
|
-
|
3137
|
-
|
3138
|
-
|
3139
|
-
variance: variance,
|
3140
|
-
variables: method_type.type.params.free_variables + method_type.block.type.params.free_variables
|
3141
|
-
)
|
3142
|
-
method_type = method_type.subst(s)
|
3143
|
-
block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
|
3144
|
-
if block_body
|
3145
|
-
block_body_type = block_constr.synthesize_block(
|
3146
|
-
node: node,
|
3147
|
-
block_body: block_body,
|
3148
|
-
block_type_hint: method_type.block.type.return_type
|
3284
|
+
method_type, solved, s = apply_solution(errors, node: node, method_type: method_type) {
|
3285
|
+
constraints.solution(
|
3286
|
+
checker,
|
3287
|
+
variables: method_type.type.params.free_variables + method_type.block.type.params.free_variables,
|
3288
|
+
context: ccontext
|
3149
3289
|
)
|
3150
|
-
|
3151
|
-
|
3152
|
-
|
3290
|
+
}
|
3291
|
+
|
3292
|
+
if solved
|
3293
|
+
# Ready for type check the body of the block
|
3294
|
+
block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
|
3295
|
+
if block_body
|
3296
|
+
block_body_type = block_constr.synthesize_block(
|
3297
|
+
node: node,
|
3298
|
+
block_body: block_body,
|
3299
|
+
block_type_hint: method_type.block.type.return_type
|
3300
|
+
)
|
3301
|
+
else
|
3302
|
+
block_body_type = AST::Builtin.nil_type
|
3303
|
+
end
|
3153
3304
|
|
3154
|
-
|
3155
|
-
|
3156
|
-
|
3305
|
+
result = check_relation(sub_type: block_body_type,
|
3306
|
+
super_type: method_type.block.type.return_type,
|
3307
|
+
constraints: constraints)
|
3157
3308
|
|
3158
|
-
|
3159
|
-
|
3160
|
-
|
3161
|
-
|
3162
|
-
|
3163
|
-
|
3164
|
-
class_type: module_context.module_type,
|
3165
|
-
variance: variance,
|
3166
|
-
variables: fresh_vars
|
3167
|
-
)
|
3168
|
-
method_type = method_type.subst(s)
|
3309
|
+
if result.success?
|
3310
|
+
# Successfully type checked the body
|
3311
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) do
|
3312
|
+
constraints.solution(checker, variables: type_param_names, context: ccontext)
|
3313
|
+
end
|
3314
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3169
3315
|
|
3170
|
-
|
3171
|
-
|
3172
|
-
|
3316
|
+
return_type = method_type.type.return_type
|
3317
|
+
if break_type = block_annotations.break_type
|
3318
|
+
return_type = union_type(break_type, return_type)
|
3319
|
+
end
|
3320
|
+
else
|
3321
|
+
# The block body has incompatible type
|
3322
|
+
errors << Diagnostic::Ruby::BlockBodyTypeMismatch.new(
|
3323
|
+
node: node,
|
3324
|
+
expected: method_type.block.type.return_type,
|
3325
|
+
actual: block_body_type,
|
3326
|
+
result: result
|
3327
|
+
)
|
3328
|
+
|
3329
|
+
method_type = eliminate_vars(method_type, type_param_names)
|
3330
|
+
return_type = method_type.type.return_type
|
3173
3331
|
end
|
3174
3332
|
|
3175
|
-
|
3176
|
-
|
3177
|
-
|
3178
|
-
|
3179
|
-
|
3180
|
-
|
3181
|
-
)
|
3333
|
+
block_constr.typing.save!
|
3334
|
+
else
|
3335
|
+
# Failed to infer the type of block parameters
|
3336
|
+
constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
|
3337
|
+
errors << error
|
3338
|
+
end
|
3182
3339
|
|
3340
|
+
method_type = eliminate_vars(method_type, type_param_names)
|
3183
3341
|
return_type = method_type.type.return_type
|
3184
3342
|
end
|
3185
|
-
|
3186
|
-
|
3187
|
-
|
3188
|
-
|
3189
|
-
|
3190
|
-
node: node,
|
3191
|
-
method_type: method_type,
|
3192
|
-
var: exn.var,
|
3193
|
-
sub_type: exn.sub_type,
|
3194
|
-
super_type: exn.super_type,
|
3195
|
-
result: exn.result
|
3343
|
+
else
|
3344
|
+
# Block parameters are unsupported syntax
|
3345
|
+
errors << Diagnostic::Ruby::UnsupportedSyntax.new(
|
3346
|
+
node: block_params,
|
3347
|
+
message: "Unsupported block params pattern, probably masgn?"
|
3196
3348
|
)
|
3197
3349
|
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3350
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3351
|
+
constraints.solution(checker, variables: type_param_names, context: ccontext)
|
3352
|
+
}
|
3353
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3201
3354
|
|
3202
|
-
|
3203
|
-
Array.new(method_type.free_variables.size, AST::Builtin.any_type))
|
3204
|
-
method_type = method_type.subst(s)
|
3355
|
+
return_type = method_type.type.return_type
|
3205
3356
|
end
|
3206
3357
|
else
|
3207
|
-
|
3208
|
-
|
3209
|
-
|
3210
|
-
|
3358
|
+
# Block is given but method doesn't accept
|
3359
|
+
#
|
3360
|
+
constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
|
3361
|
+
errors << error
|
3362
|
+
end
|
3211
3363
|
|
3212
|
-
|
3213
|
-
|
3214
|
-
|
3215
|
-
variables: fresh_vars,
|
3216
|
-
self_type: self_type,
|
3217
|
-
instance_type: module_context.instance_type,
|
3218
|
-
class_type: module_context.module_type
|
3364
|
+
errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
|
3365
|
+
node: node,
|
3366
|
+
method_type: method_type
|
3219
3367
|
)
|
3220
|
-
|
3368
|
+
|
3369
|
+
method_type = eliminate_vars(method_type, type_param_names)
|
3370
|
+
return_type = method_type.type.return_type
|
3221
3371
|
end
|
3222
3372
|
else
|
3223
|
-
# Block is given
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3373
|
+
# Block syntax is not given
|
3374
|
+
arg = args.block_pass_arg
|
3375
|
+
|
3376
|
+
case
|
3377
|
+
when arg.compatible?
|
3378
|
+
if arg.node
|
3379
|
+
# Block pass (&block) is given
|
3380
|
+
node_type, constr = constr.synthesize(arg.node, hint: arg.node_type)
|
3381
|
+
|
3382
|
+
nil_given =
|
3383
|
+
constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success? &&
|
3384
|
+
!node_type.is_a?(AST::Types::Any)
|
3385
|
+
|
3386
|
+
if nil_given
|
3387
|
+
# nil is given ==> no block arg node is given
|
3388
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3389
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3390
|
+
}
|
3391
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3228
3392
|
|
3229
|
-
|
3230
|
-
|
3231
|
-
|
3232
|
-
|
3233
|
-
|
3234
|
-
|
3235
|
-
|
3393
|
+
# Passing no block
|
3394
|
+
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3395
|
+
node: node,
|
3396
|
+
method_type: method_type
|
3397
|
+
)
|
3398
|
+
else
|
3399
|
+
# non-nil value is given
|
3400
|
+
constr.check_relation(sub_type: node_type, super_type: arg.node_type, constraints: constraints).else do |result|
|
3401
|
+
errors << Diagnostic::Ruby::BlockTypeMismatch.new(
|
3402
|
+
node: arg.node,
|
3403
|
+
expected: arg.node_type,
|
3404
|
+
actual: node_type,
|
3405
|
+
result: result
|
3406
|
+
)
|
3407
|
+
end
|
3236
3408
|
|
3237
|
-
|
3238
|
-
|
3239
|
-
|
3240
|
-
|
3241
|
-
|
3242
|
-
|
3243
|
-
|
3244
|
-
|
3245
|
-
|
3246
|
-
|
3247
|
-
|
3409
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3410
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3411
|
+
}
|
3412
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3413
|
+
end
|
3414
|
+
else
|
3415
|
+
# Block is not given
|
3416
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3417
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3418
|
+
}
|
3419
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3420
|
+
end
|
3248
3421
|
|
3249
|
-
|
3422
|
+
return_type = method_type.type.return_type
|
3250
3423
|
|
3251
|
-
|
3252
|
-
|
3253
|
-
|
3254
|
-
|
3424
|
+
when arg.block_missing?
|
3425
|
+
# Block is required but not given
|
3426
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3427
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3428
|
+
}
|
3255
3429
|
|
3256
|
-
unless
|
3257
|
-
|
3258
|
-
errors << Diagnostic::Ruby::BlockTypeMismatch.new(
|
3259
|
-
node: arg.node,
|
3260
|
-
expected: block_type,
|
3261
|
-
actual: node_type,
|
3262
|
-
result: result
|
3263
|
-
)
|
3264
|
-
end
|
3265
|
-
end
|
3430
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3431
|
+
return_type = method_type.type.return_type
|
3266
3432
|
|
3267
|
-
|
3268
|
-
|
3269
|
-
|
3270
|
-
instance_type: module_context.instance_type,
|
3271
|
-
class_type: module_context.module_type,
|
3272
|
-
variance: variance,
|
3273
|
-
variables: method_type.free_variables
|
3433
|
+
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3434
|
+
node: node,
|
3435
|
+
method_type: method_type
|
3274
3436
|
)
|
3275
3437
|
|
3276
|
-
|
3438
|
+
when arg.unexpected_block?
|
3439
|
+
# Unexpected block is given
|
3440
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3441
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3442
|
+
}
|
3443
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3444
|
+
return_type = method_type.type.return_type
|
3277
3445
|
|
3278
|
-
|
3279
|
-
|
3280
|
-
|
3446
|
+
node_type, constr = constr.synthesize(arg.node)
|
3447
|
+
|
3448
|
+
unless constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success?
|
3449
|
+
errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
|
3281
3450
|
node: node,
|
3282
3451
|
method_type: method_type
|
3283
3452
|
)
|
3284
3453
|
end
|
3285
|
-
else
|
3286
|
-
subst = constraints.solution(
|
3287
|
-
checker,
|
3288
|
-
self_type: self_type,
|
3289
|
-
instance_type: module_context.instance_type,
|
3290
|
-
class_type: module_context.module_type,
|
3291
|
-
variance: variance,
|
3292
|
-
variables: method_type.free_variables
|
3293
|
-
)
|
3294
|
-
|
3295
|
-
method_type = method_type.subst(subst)
|
3296
|
-
end
|
3297
|
-
|
3298
|
-
when arg.block_missing?
|
3299
|
-
subst = constraints.solution(
|
3300
|
-
checker,
|
3301
|
-
self_type: self_type,
|
3302
|
-
instance_type: module_context.instance_type,
|
3303
|
-
class_type: module_context.module_type,
|
3304
|
-
variance: variance,
|
3305
|
-
variables: method_type.free_variables
|
3306
|
-
)
|
3307
|
-
|
3308
|
-
method_type = method_type.subst(subst)
|
3309
|
-
|
3310
|
-
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3311
|
-
node: node,
|
3312
|
-
method_type: method_type
|
3313
|
-
)
|
3314
|
-
|
3315
|
-
when arg.unexpected_block?
|
3316
|
-
subst = constraints.solution(
|
3317
|
-
checker,
|
3318
|
-
self_type: self_type,
|
3319
|
-
instance_type: module_context.instance_type,
|
3320
|
-
class_type: module_context.module_type,
|
3321
|
-
variance: variance,
|
3322
|
-
variables: method_type.free_variables
|
3323
|
-
)
|
3324
|
-
|
3325
|
-
method_type = method_type.subst(subst)
|
3326
|
-
|
3327
|
-
node_type, constr = constr.synthesize(arg.node)
|
3328
|
-
|
3329
|
-
unless constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success?
|
3330
|
-
errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
|
3331
|
-
node: node,
|
3332
|
-
method_type: method_type
|
3333
|
-
)
|
3334
3454
|
end
|
3335
3455
|
end
|
3336
|
-
end
|
3337
3456
|
|
3338
|
-
|
3339
|
-
|
3340
|
-
|
3341
|
-
|
3342
|
-
|
3343
|
-
|
3344
|
-
|
3345
|
-
|
3346
|
-
|
3347
|
-
|
3348
|
-
|
3349
|
-
|
3350
|
-
|
3351
|
-
|
3352
|
-
|
3353
|
-
|
3354
|
-
|
3355
|
-
|
3356
|
-
|
3357
|
-
|
3358
|
-
|
3359
|
-
|
3360
|
-
|
3361
|
-
|
3362
|
-
|
3363
|
-
|
3457
|
+
call = if errors.empty?
|
3458
|
+
TypeInference::MethodCall::Typed.new(
|
3459
|
+
node: node,
|
3460
|
+
context: context.method_context,
|
3461
|
+
receiver_type: receiver_type,
|
3462
|
+
method_name: method_name,
|
3463
|
+
actual_method_type: method_type,
|
3464
|
+
return_type: return_type || method_type.type.return_type,
|
3465
|
+
method_decls: method_type.method_decls
|
3466
|
+
)
|
3467
|
+
else
|
3468
|
+
TypeInference::MethodCall::Error.new(
|
3469
|
+
node: node,
|
3470
|
+
context: context.method_context,
|
3471
|
+
receiver_type: receiver_type,
|
3472
|
+
method_name: method_name,
|
3473
|
+
return_type: return_type || method_type.type.return_type,
|
3474
|
+
method_decls: method_type.method_decls,
|
3475
|
+
errors: errors
|
3476
|
+
)
|
3477
|
+
end
|
3478
|
+
|
3479
|
+
[
|
3480
|
+
call,
|
3481
|
+
constr
|
3482
|
+
]
|
3483
|
+
end
|
3364
3484
|
end
|
3365
3485
|
|
3366
3486
|
def type_check_argument(node, receiver_type:, type:, constraints:, report_node: node, errors:)
|
@@ -3485,7 +3605,8 @@ module Steep
|
|
3485
3605
|
self_type: self_type,
|
3486
3606
|
type_env: type_env.dup,
|
3487
3607
|
lvar_env: lvar_env,
|
3488
|
-
call_context: self.context.call_context
|
3608
|
+
call_context: self.context.call_context,
|
3609
|
+
variable_context: variable_context
|
3489
3610
|
)
|
3490
3611
|
)
|
3491
3612
|
end
|