steep 0.47.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|