steep 0.47.1 → 0.49.1
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 +24 -0
- data/Gemfile.lock +7 -7
- data/lib/steep/ast/types/any.rb +2 -0
- data/lib/steep/ast/types/boolean.rb +2 -0
- data/lib/steep/ast/types/bot.rb +2 -0
- data/lib/steep/ast/types/class.rb +2 -0
- data/lib/steep/ast/types/factory.rb +162 -138
- data/lib/steep/ast/types/helper.rb +8 -0
- data/lib/steep/ast/types/instance.rb +2 -0
- data/lib/steep/ast/types/intersection.rb +4 -0
- data/lib/steep/ast/types/literal.rb +2 -0
- data/lib/steep/ast/types/logic.rb +2 -0
- data/lib/steep/ast/types/name.rb +6 -0
- data/lib/steep/ast/types/nil.rb +2 -0
- data/lib/steep/ast/types/proc.rb +9 -0
- data/lib/steep/ast/types/record.rb +4 -0
- data/lib/steep/ast/types/self.rb +2 -0
- data/lib/steep/ast/types/top.rb +2 -0
- data/lib/steep/ast/types/tuple.rb +4 -0
- data/lib/steep/ast/types/union.rb +4 -0
- data/lib/steep/ast/types/var.rb +16 -3
- data/lib/steep/ast/types/void.rb +2 -0
- data/lib/steep/diagnostic/ruby.rb +36 -11
- data/lib/steep/diagnostic/signature.rb +56 -0
- data/lib/steep/drivers/check.rb +2 -2
- data/lib/steep/interface/function.rb +4 -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 +4 -1
- data/lib/steep/signature/validator.rb +228 -49
- data/lib/steep/subtyping/cache.rb +30 -0
- data/lib/steep/subtyping/check.rb +600 -705
- 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 +576 -395
- data/lib/steep/type_inference/block_params.rb +31 -3
- 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/proc_type_expected.rb +3 -0
- data/smoke/diagnostics/test_expectations.yml +12 -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/smoke/tsort/a.rb +1 -1
- data/smoke/tsort/test_expectations.yml +1 -63
- data/steep.gemspec +1 -1
- metadata +14 -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(
|
@@ -930,7 +1005,7 @@ module Steep
|
|
930
1005
|
yield_self do
|
931
1006
|
send_node, params, body = node.children
|
932
1007
|
if send_node.type == :lambda
|
933
|
-
type_lambda(node,
|
1008
|
+
type_lambda(node, params_node: params, body_node: body, type_hint: hint)
|
934
1009
|
else
|
935
1010
|
type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend)
|
936
1011
|
end
|
@@ -949,7 +1024,7 @@ module Steep
|
|
949
1024
|
params = Parser::AST::Node.new(:args, arg_nodes)
|
950
1025
|
|
951
1026
|
if send_node.type == :lambda
|
952
|
-
type_lambda(node,
|
1027
|
+
type_lambda(node, params_node: params, body_node: body, type_hint: hint)
|
953
1028
|
else
|
954
1029
|
type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend)
|
955
1030
|
end
|
@@ -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
|
@@ -1105,16 +1181,18 @@ module Steep
|
|
1105
1181
|
|
1106
1182
|
when :return
|
1107
1183
|
yield_self do
|
1108
|
-
|
1109
|
-
method_return_type = expand_alias(method_context&.return_type)
|
1184
|
+
method_return_type = expand_alias(method_context&.return_type)
|
1110
1185
|
|
1186
|
+
if node.children.size > 0
|
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
|
@@ -1123,20 +1201,23 @@ module Steep
|
|
1123
1201
|
AST::Builtin::Array.instance_type(union_type(*return_types))
|
1124
1202
|
end
|
1125
1203
|
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1204
|
+
else
|
1205
|
+
value_type = AST::Builtin.nil_type
|
1206
|
+
end
|
1207
|
+
|
1208
|
+
if method_return_type
|
1209
|
+
unless method_return_type.is_a?(AST::Types::Void)
|
1210
|
+
result = check_relation(sub_type: value_type, super_type: method_return_type)
|
1129
1211
|
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
)
|
1212
|
+
if result.failure?
|
1213
|
+
typing.add_error(
|
1214
|
+
Diagnostic::Ruby::ReturnTypeMismatch.new(
|
1215
|
+
node: node,
|
1216
|
+
expected: method_context&.return_type,
|
1217
|
+
actual: value_type,
|
1218
|
+
result: result
|
1138
1219
|
)
|
1139
|
-
|
1220
|
+
)
|
1140
1221
|
end
|
1141
1222
|
end
|
1142
1223
|
end
|
@@ -1427,7 +1508,7 @@ module Steep
|
|
1427
1508
|
end
|
1428
1509
|
_, constr = constr.synthesize(sup) if sup
|
1429
1510
|
|
1430
|
-
|
1511
|
+
with_class_constr(node) do |constructor|
|
1431
1512
|
if module_type = constructor.module_context&.module_type
|
1432
1513
|
_, constructor = constructor.add_typing(name, type: module_type)
|
1433
1514
|
else
|
@@ -1467,7 +1548,7 @@ module Steep
|
|
1467
1548
|
_, constr = constr.synthesize(name)
|
1468
1549
|
end
|
1469
1550
|
|
1470
|
-
|
1551
|
+
with_module_constr(node) do |constructor|
|
1471
1552
|
if module_type = constructor.module_context&.module_type
|
1472
1553
|
_, constructor = constructor.add_typing(name, type: module_type)
|
1473
1554
|
else
|
@@ -1495,27 +1576,28 @@ module Steep
|
|
1495
1576
|
when :sclass
|
1496
1577
|
yield_self do
|
1497
1578
|
type, constr = synthesize(node.children[0])
|
1498
|
-
constructor = constr.for_sclass(node, type)
|
1499
1579
|
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1580
|
+
with_sclass_constr(node, type) do |constructor|
|
1581
|
+
unless constructor
|
1582
|
+
typing.add_error(
|
1583
|
+
Diagnostic::Ruby::UnsupportedSyntax.new(
|
1584
|
+
node: node,
|
1585
|
+
message: "sclass receiver must be instance type or singleton type, but type given `#{type}`"
|
1586
|
+
)
|
1505
1587
|
)
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
end
|
1588
|
+
constr.add_typing(node, type: AST::Builtin.nil_type)
|
1589
|
+
return
|
1590
|
+
end
|
1510
1591
|
|
1511
|
-
|
1512
|
-
|
1592
|
+
constructor.typing.add_context_for_node(node, context: constructor.context)
|
1593
|
+
constructor.typing.add_context_for_body(node, context: constructor.context)
|
1513
1594
|
|
1514
|
-
|
1595
|
+
constructor.synthesize(node.children[1]) if node.children[1]
|
1515
1596
|
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1597
|
+
if constructor.module_context.instance_definition && module_context.module_definition
|
1598
|
+
if constructor.module_context.instance_definition.type_name == module_context.module_definition.type_name
|
1599
|
+
module_context.defined_module_methods.merge(constructor.module_context.defined_instance_methods)
|
1600
|
+
end
|
1519
1601
|
end
|
1520
1602
|
end
|
1521
1603
|
|
@@ -1573,8 +1655,7 @@ module Steep
|
|
1573
1655
|
instance_type: module_context.instance_type,
|
1574
1656
|
class_type: module_context.module_type
|
1575
1657
|
) do |error|
|
1576
|
-
|
1577
|
-
when Subtyping::Result::Failure
|
1658
|
+
if error
|
1578
1659
|
const_type = type_env.get(const: const_name)
|
1579
1660
|
typing.add_error(
|
1580
1661
|
Diagnostic::Ruby::IncompatibleAssignment.new(
|
@@ -1584,7 +1665,7 @@ module Steep
|
|
1584
1665
|
result: error
|
1585
1666
|
)
|
1586
1667
|
)
|
1587
|
-
|
1668
|
+
else
|
1588
1669
|
typing.add_error(
|
1589
1670
|
Diagnostic::Ruby::UnknownConstantAssigned.new(
|
1590
1671
|
node: node,
|
@@ -2385,7 +2466,7 @@ module Steep
|
|
2385
2466
|
raise "#synthesize should return an instance of Pair: #{pair.class}, node=#{node.inspect}"
|
2386
2467
|
end
|
2387
2468
|
end
|
2388
|
-
rescue RBS::
|
2469
|
+
rescue RBS::BaseError => exn
|
2389
2470
|
Steep.logger.warn { "Unexpected RBS error: #{exn.message}" }
|
2390
2471
|
exn.backtrace.each {|loc| Steep.logger.warn " #{loc}" }
|
2391
2472
|
typing.add_error(Diagnostic::Ruby::UnexpectedError.new(node: node, error: exn))
|
@@ -2411,6 +2492,7 @@ module Steep
|
|
2411
2492
|
|
2412
2493
|
def type_ivasgn(name, rhs, node)
|
2413
2494
|
rhs_type = synthesize(rhs, hint: type_env.get(ivar: name) { fallback_to_any(node) }).type
|
2495
|
+
|
2414
2496
|
ivar_type = type_env.assign(
|
2415
2497
|
ivar: name,
|
2416
2498
|
type: rhs_type,
|
@@ -2418,8 +2500,7 @@ module Steep
|
|
2418
2500
|
instance_type: module_context.instance_type,
|
2419
2501
|
class_type: module_context.module_type
|
2420
2502
|
) do |error|
|
2421
|
-
|
2422
|
-
when Subtyping::Result::Failure
|
2503
|
+
if error
|
2423
2504
|
type = type_env.get(ivar: name)
|
2424
2505
|
typing.add_error(
|
2425
2506
|
Diagnostic::Ruby::IncompatibleAssignment.new(
|
@@ -2429,7 +2510,7 @@ module Steep
|
|
2429
2510
|
result: error
|
2430
2511
|
)
|
2431
2512
|
)
|
2432
|
-
|
2513
|
+
else
|
2433
2514
|
fallback_to_any node
|
2434
2515
|
end
|
2435
2516
|
end
|
@@ -2473,8 +2554,7 @@ module Steep
|
|
2473
2554
|
instance_type: module_context.instance_type,
|
2474
2555
|
class_type: module_context.module_type
|
2475
2556
|
) do |error|
|
2476
|
-
|
2477
|
-
when Subtyping::Result::Failure
|
2557
|
+
if error
|
2478
2558
|
var_type = type_env.get(ivar: ivar)
|
2479
2559
|
typing.add_error(
|
2480
2560
|
Diagnostic::Ruby::IncompatibleAssignment.new(
|
@@ -2484,7 +2564,7 @@ module Steep
|
|
2484
2564
|
result: error
|
2485
2565
|
)
|
2486
2566
|
)
|
2487
|
-
|
2567
|
+
else
|
2488
2568
|
fallback_to_any node
|
2489
2569
|
end
|
2490
2570
|
end
|
@@ -2647,34 +2727,89 @@ module Steep
|
|
2647
2727
|
end
|
2648
2728
|
end
|
2649
2729
|
|
2650
|
-
def
|
2730
|
+
def optional_proc?(type)
|
2731
|
+
if type.is_a?(AST::Types::Union)
|
2732
|
+
if type.types.size == 2
|
2733
|
+
if type.types.find {|t| t.is_a?(AST::Types::Nil) }
|
2734
|
+
if proc_type = type.types.find {|t| t.is_a?(AST::Types::Proc) }
|
2735
|
+
proc_type
|
2736
|
+
end
|
2737
|
+
end
|
2738
|
+
end
|
2739
|
+
end
|
2740
|
+
end
|
2741
|
+
|
2742
|
+
def type_lambda(node, params_node:, body_node:, type_hint:)
|
2651
2743
|
block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
2652
|
-
params = TypeInference::BlockParams.from_node(
|
2744
|
+
params = TypeInference::BlockParams.from_node(params_node, annotations: block_annotations)
|
2745
|
+
|
2746
|
+
type_hint = deep_expand_alias(type_hint) if type_hint
|
2653
2747
|
|
2654
2748
|
case type_hint
|
2655
2749
|
when AST::Types::Proc
|
2656
2750
|
params_hint = type_hint.type.params
|
2657
2751
|
return_hint = type_hint.type.return_type
|
2752
|
+
block_hint = type_hint.block
|
2658
2753
|
end
|
2659
2754
|
|
2660
2755
|
block_constr = for_block(
|
2661
2756
|
block_params: params,
|
2662
2757
|
block_param_hint: params_hint,
|
2663
2758
|
block_type_hint: return_hint,
|
2759
|
+
block_block_hint: block_hint,
|
2664
2760
|
block_annotations: block_annotations,
|
2665
2761
|
node_type_hint: nil
|
2666
2762
|
)
|
2667
2763
|
|
2668
2764
|
block_constr.typing.add_context_for_body(node, context: block_constr.context)
|
2669
2765
|
|
2766
|
+
default_proc_function =
|
2767
|
+
Interface::Function.new(
|
2768
|
+
params: Interface::Function::Params.empty,
|
2769
|
+
return_type: AST::Builtin.any_type,
|
2770
|
+
location: nil
|
2771
|
+
)
|
2772
|
+
|
2670
2773
|
params.params.each do |param|
|
2671
2774
|
_, block_constr = block_constr.synthesize(param.node, hint: param.type)
|
2672
2775
|
end
|
2673
2776
|
|
2674
|
-
|
2777
|
+
block =
|
2778
|
+
if block_param = params.block_param
|
2779
|
+
if block_param_type = block_param.type
|
2780
|
+
case block_param_type
|
2781
|
+
when AST::Types::Proc
|
2782
|
+
Interface::Block.new(type: block_param_type.type, optional: false)
|
2783
|
+
else
|
2784
|
+
if proc_type = optional_proc?(block_param_type)
|
2785
|
+
Interface::Block.new(type: proc_type.type, optional: true)
|
2786
|
+
else
|
2787
|
+
block_constr.typing.add_error(
|
2788
|
+
Diagnostic::Ruby::ProcTypeExpected.new(
|
2789
|
+
node: block_param.node,
|
2790
|
+
type: block_param_type
|
2791
|
+
)
|
2792
|
+
)
|
2793
|
+
|
2794
|
+
Interface::Block.new(
|
2795
|
+
type: Interface::Function.new(
|
2796
|
+
params: Interface::Function::Params.empty,
|
2797
|
+
return_type: AST::Builtin.any_type,
|
2798
|
+
location: nil
|
2799
|
+
),
|
2800
|
+
optional: false
|
2801
|
+
)
|
2802
|
+
end
|
2803
|
+
end
|
2804
|
+
else
|
2805
|
+
block_hint
|
2806
|
+
end
|
2807
|
+
end
|
2808
|
+
|
2809
|
+
if body_node
|
2675
2810
|
return_type = block_constr.synthesize_block(
|
2676
2811
|
node: node,
|
2677
|
-
block_body:
|
2812
|
+
block_body: body_node,
|
2678
2813
|
block_type_hint: return_hint
|
2679
2814
|
)
|
2680
2815
|
|
@@ -2702,7 +2837,7 @@ module Steep
|
|
2702
2837
|
return_type: return_type,
|
2703
2838
|
location: nil
|
2704
2839
|
),
|
2705
|
-
block:
|
2840
|
+
block: block
|
2706
2841
|
)
|
2707
2842
|
|
2708
2843
|
add_typing node, type: block_type
|
@@ -2830,6 +2965,32 @@ module Steep
|
|
2830
2965
|
)
|
2831
2966
|
)
|
2832
2967
|
|
2968
|
+
when AST::Types::Var
|
2969
|
+
if upper_bound = variable_context[receiver_type.name]
|
2970
|
+
interface = calculate_interface(upper_bound, private: false)
|
2971
|
+
|
2972
|
+
constr.type_send_interface(
|
2973
|
+
node,
|
2974
|
+
interface: interface,
|
2975
|
+
receiver: receiver,
|
2976
|
+
receiver_type: receiver_type,
|
2977
|
+
method_name: method_name,
|
2978
|
+
arguments: arguments,
|
2979
|
+
block_params: block_params,
|
2980
|
+
block_body: block_body
|
2981
|
+
)
|
2982
|
+
else
|
2983
|
+
constr = constr.synthesize_children(node, skips: [receiver])
|
2984
|
+
constr.add_call(
|
2985
|
+
TypeInference::MethodCall::NoMethodError.new(
|
2986
|
+
node: node,
|
2987
|
+
context: context.method_context,
|
2988
|
+
method_name: method_name,
|
2989
|
+
receiver_type: receiver_type,
|
2990
|
+
error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2991
|
+
)
|
2992
|
+
)
|
2993
|
+
end
|
2833
2994
|
when AST::Types::Void, AST::Types::Bot, AST::Types::Top, AST::Types::Var
|
2834
2995
|
constr = constr.synthesize_children(node, skips: [receiver])
|
2835
2996
|
constr.add_call(
|
@@ -2872,6 +3033,7 @@ module Steep
|
|
2872
3033
|
block_params: block_params,
|
2873
3034
|
block_body: block_body)
|
2874
3035
|
end
|
3036
|
+
|
2875
3037
|
else
|
2876
3038
|
interface = calculate_interface(receiver_type, private: private, self_type: receiver_type)
|
2877
3039
|
|
@@ -2991,119 +3153,166 @@ module Steep
|
|
2991
3153
|
end
|
2992
3154
|
end
|
2993
3155
|
|
3156
|
+
def apply_solution(errors, node:, method_type:)
|
3157
|
+
subst = yield
|
3158
|
+
|
3159
|
+
[
|
3160
|
+
method_type.subst(subst),
|
3161
|
+
true,
|
3162
|
+
subst
|
3163
|
+
]
|
3164
|
+
|
3165
|
+
rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
|
3166
|
+
errors << Diagnostic::Ruby::UnsatisfiableConstraint.new(
|
3167
|
+
node: node,
|
3168
|
+
method_type: method_type,
|
3169
|
+
var: exn.var,
|
3170
|
+
sub_type: exn.sub_type,
|
3171
|
+
super_type: exn.super_type,
|
3172
|
+
result: exn.result
|
3173
|
+
)
|
3174
|
+
[method_type, false, Interface::Substitution.empty]
|
3175
|
+
end
|
3176
|
+
|
3177
|
+
def eliminate_vars(type, variables, to: AST::Builtin.any_type)
|
3178
|
+
if variables.empty?
|
3179
|
+
type
|
3180
|
+
else
|
3181
|
+
subst = Interface::Substitution.build(variables, Array.new(variables.size, to))
|
3182
|
+
type.subst(subst)
|
3183
|
+
end
|
3184
|
+
end
|
3185
|
+
|
2994
3186
|
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)
|
3187
|
+
type_params, instantiation = Interface::TypeParam.rename(method_type.type_params)
|
3188
|
+
type_param_names = type_params.map(&:name)
|
2998
3189
|
|
2999
3190
|
constr = self
|
3000
3191
|
|
3001
3192
|
method_type = method_type.instantiate(instantiation)
|
3002
3193
|
|
3003
|
-
constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
|
3004
3194
|
variance = Subtyping::VariableVariance.from_method_type(method_type)
|
3005
3195
|
occurence = Subtyping::VariableOccurence.from_method_type(method_type)
|
3196
|
+
constraints = Subtyping::Constraints.new(unknowns: type_params.map(&:name))
|
3197
|
+
ccontext = Subtyping::Constraints::Context.new(
|
3198
|
+
self_type: self_type,
|
3199
|
+
instance_type: module_context.instance_type,
|
3200
|
+
class_type: module_context.module_type,
|
3201
|
+
variance: variance
|
3202
|
+
)
|
3006
3203
|
|
3007
|
-
|
3204
|
+
upper_bounds = {}
|
3008
3205
|
|
3009
|
-
|
3010
|
-
|
3011
|
-
|
3012
|
-
|
3013
|
-
|
3014
|
-
|
3015
|
-
type: arg.param.type,
|
3016
|
-
receiver_type: receiver_type,
|
3017
|
-
constraints: constraints,
|
3018
|
-
errors: errors
|
3019
|
-
)
|
3206
|
+
type_params.each do |param|
|
3207
|
+
if ub = param.upper_bound
|
3208
|
+
constraints.add(param.name, super_type: ub, skip: true)
|
3209
|
+
upper_bounds[param.name] = ub
|
3210
|
+
end
|
3211
|
+
end
|
3020
3212
|
|
3021
|
-
|
3022
|
-
|
3023
|
-
|
3024
|
-
|
3025
|
-
|
3213
|
+
checker.push_variable_bounds(upper_bounds) do
|
3214
|
+
errors = []
|
3215
|
+
|
3216
|
+
args = TypeInference::SendArgs.new(node: node, arguments: arguments, method_name: method_name, method_type: method_type)
|
3217
|
+
es = args.each do |arg|
|
3218
|
+
case arg
|
3219
|
+
when TypeInference::SendArgs::PositionalArgs::NodeParamPair
|
3220
|
+
_, constr = constr.type_check_argument(
|
3221
|
+
arg.node,
|
3222
|
+
type: arg.param.type,
|
3026
3223
|
receiver_type: receiver_type,
|
3027
3224
|
constraints: constraints,
|
3028
|
-
report_node: arg.node,
|
3029
3225
|
errors: errors
|
3030
3226
|
)
|
3031
|
-
end
|
3032
3227
|
|
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|
|
3228
|
+
when TypeInference::SendArgs::PositionalArgs::NodeTypePair
|
3229
|
+
_, constr = bypass_splat(arg.node) do |n|
|
3050
3230
|
constr.type_check_argument(
|
3051
|
-
|
3052
|
-
type:
|
3231
|
+
n,
|
3232
|
+
type: arg.node_type,
|
3053
3233
|
receiver_type: receiver_type,
|
3054
3234
|
constraints: constraints,
|
3235
|
+
report_node: arg.node,
|
3055
3236
|
errors: errors
|
3056
3237
|
)
|
3057
3238
|
end
|
3058
|
-
end
|
3059
3239
|
|
3060
|
-
|
3061
|
-
if arg.node.type == :pair
|
3062
|
-
arg.node.children.each do |nn|
|
3063
|
-
_, constr = constr.synthesize(nn)
|
3064
|
-
end
|
3065
|
-
else
|
3240
|
+
when TypeInference::SendArgs::PositionalArgs::UnexpectedArg
|
3066
3241
|
_, constr = bypass_splat(arg.node) do |n|
|
3067
3242
|
constr.synthesize(n)
|
3068
3243
|
end
|
3069
|
-
end
|
3070
3244
|
|
3071
|
-
|
3072
|
-
|
3073
|
-
|
3074
|
-
|
3245
|
+
when TypeInference::SendArgs::PositionalArgs::SplatArg
|
3246
|
+
arg_type, _ = constr
|
3247
|
+
.with_child_typing(range: arg.node.loc.expression.begin_pos ... arg.node.loc.expression.end_pos)
|
3248
|
+
.try_tuple_type!(arg.node.children[0])
|
3249
|
+
arg.type = arg_type
|
3250
|
+
|
3251
|
+
when TypeInference::SendArgs::PositionalArgs::MissingArg
|
3252
|
+
# ignore
|
3253
|
+
|
3254
|
+
when TypeInference::SendArgs::KeywordArgs::ArgTypePairs
|
3255
|
+
arg.pairs.each do |node, type|
|
3256
|
+
_, constr = bypass_splat(node) do |node|
|
3257
|
+
constr.type_check_argument(
|
3258
|
+
node,
|
3259
|
+
type: type,
|
3260
|
+
receiver_type: receiver_type,
|
3261
|
+
constraints: constraints,
|
3262
|
+
errors: errors
|
3263
|
+
)
|
3264
|
+
end
|
3075
3265
|
end
|
3076
3266
|
|
3077
|
-
|
3078
|
-
|
3267
|
+
when TypeInference::SendArgs::KeywordArgs::UnexpectedKeyword
|
3268
|
+
if arg.node.type == :pair
|
3269
|
+
arg.node.children.each do |nn|
|
3270
|
+
_, constr = constr.synthesize(nn)
|
3271
|
+
end
|
3272
|
+
else
|
3273
|
+
_, constr = bypass_splat(arg.node) do |n|
|
3274
|
+
constr.synthesize(n)
|
3275
|
+
end
|
3276
|
+
end
|
3277
|
+
|
3278
|
+
when TypeInference::SendArgs::KeywordArgs::SplatArg
|
3279
|
+
type, _ = bypass_splat(arg.node) do |sp_node|
|
3280
|
+
if sp_node.type == :hash
|
3281
|
+
pair = constr.type_hash_record(sp_node, nil) and break pair
|
3282
|
+
end
|
3079
3283
|
|
3080
|
-
|
3284
|
+
constr.synthesize(sp_node)
|
3285
|
+
end
|
3081
3286
|
|
3082
|
-
|
3083
|
-
# ignore
|
3084
|
-
else
|
3085
|
-
raise arg.inspect
|
3086
|
-
end
|
3287
|
+
arg.type = type
|
3087
3288
|
|
3088
|
-
|
3089
|
-
|
3289
|
+
when TypeInference::SendArgs::KeywordArgs::MissingKeyword
|
3290
|
+
# ignore
|
3291
|
+
else
|
3292
|
+
raise arg.inspect
|
3293
|
+
end
|
3090
3294
|
|
3091
|
-
|
3295
|
+
constr
|
3296
|
+
end
|
3297
|
+
|
3298
|
+
errors.push(*es)
|
3092
3299
|
|
3093
|
-
|
3094
|
-
|
3095
|
-
|
3096
|
-
|
3300
|
+
if block_params
|
3301
|
+
# block is given
|
3302
|
+
block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
3303
|
+
block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
3097
3304
|
|
3098
|
-
|
3099
|
-
|
3305
|
+
if method_type.block
|
3306
|
+
# Method accepts block
|
3307
|
+
pairs = method_type.block && block_params_&.zip(method_type.block.type.params, nil)
|
3100
3308
|
|
3101
|
-
|
3102
|
-
|
3309
|
+
if pairs
|
3310
|
+
# Block parameters are compatible with the block type
|
3103
3311
|
block_constr = constr.for_block(
|
3104
3312
|
block_params: block_params_,
|
3105
3313
|
block_param_hint: method_type.block.type.params,
|
3106
3314
|
block_type_hint: method_type.block.type.return_type,
|
3315
|
+
block_block_hint: nil,
|
3107
3316
|
block_annotations: block_annotations,
|
3108
3317
|
node_type_hint: method_type.type.return_type
|
3109
3318
|
)
|
@@ -3131,236 +3340,206 @@ module Steep
|
|
3131
3340
|
end
|
3132
3341
|
end
|
3133
3342
|
|
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
|
3343
|
+
method_type, solved, s = apply_solution(errors, node: node, method_type: method_type) {
|
3344
|
+
constraints.solution(
|
3345
|
+
checker,
|
3346
|
+
variables: method_type.type.params.free_variables + method_type.block.type.params.free_variables,
|
3347
|
+
context: ccontext
|
3149
3348
|
)
|
3150
|
-
|
3151
|
-
block_body_type = AST::Builtin.nil_type
|
3152
|
-
end
|
3349
|
+
}
|
3153
3350
|
|
3154
|
-
|
3155
|
-
|
3156
|
-
|
3351
|
+
if solved
|
3352
|
+
# Ready for type check the body of the block
|
3353
|
+
block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
|
3354
|
+
if block_body
|
3355
|
+
block_body_type = block_constr.synthesize_block(
|
3356
|
+
node: node,
|
3357
|
+
block_body: block_body,
|
3358
|
+
block_type_hint: method_type.block.type.return_type
|
3359
|
+
)
|
3360
|
+
else
|
3361
|
+
block_body_type = AST::Builtin.nil_type
|
3362
|
+
end
|
3157
3363
|
|
3158
|
-
|
3159
|
-
|
3160
|
-
|
3161
|
-
checker,
|
3162
|
-
self_type: self_type,
|
3163
|
-
instance_type: module_context.instance_type,
|
3164
|
-
class_type: module_context.module_type,
|
3165
|
-
variance: variance,
|
3166
|
-
variables: fresh_vars
|
3167
|
-
)
|
3168
|
-
method_type = method_type.subst(s)
|
3364
|
+
result = check_relation(sub_type: block_body_type,
|
3365
|
+
super_type: method_type.block.type.return_type,
|
3366
|
+
constraints: constraints)
|
3169
3367
|
|
3170
|
-
|
3171
|
-
|
3172
|
-
|
3368
|
+
if result.success?
|
3369
|
+
# Successfully type checked the body
|
3370
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) do
|
3371
|
+
constraints.solution(checker, variables: type_param_names, context: ccontext)
|
3372
|
+
end
|
3373
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3374
|
+
|
3375
|
+
return_type = method_type.type.return_type
|
3376
|
+
if break_type = block_annotations.break_type
|
3377
|
+
return_type = union_type(break_type, return_type)
|
3378
|
+
end
|
3379
|
+
else
|
3380
|
+
# The block body has incompatible type
|
3381
|
+
errors << Diagnostic::Ruby::BlockBodyTypeMismatch.new(
|
3382
|
+
node: node,
|
3383
|
+
expected: method_type.block.type.return_type,
|
3384
|
+
actual: block_body_type,
|
3385
|
+
result: result
|
3386
|
+
)
|
3387
|
+
|
3388
|
+
method_type = eliminate_vars(method_type, type_param_names)
|
3389
|
+
return_type = method_type.type.return_type
|
3173
3390
|
end
|
3174
3391
|
|
3175
|
-
|
3176
|
-
|
3177
|
-
|
3178
|
-
|
3179
|
-
|
3180
|
-
|
3181
|
-
)
|
3392
|
+
block_constr.typing.save!
|
3393
|
+
else
|
3394
|
+
# Failed to infer the type of block parameters
|
3395
|
+
constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
|
3396
|
+
errors << error
|
3397
|
+
end
|
3182
3398
|
|
3399
|
+
method_type = eliminate_vars(method_type, type_param_names)
|
3183
3400
|
return_type = method_type.type.return_type
|
3184
3401
|
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
|
3402
|
+
else
|
3403
|
+
# Block parameters are unsupported syntax
|
3404
|
+
errors << Diagnostic::Ruby::UnsupportedSyntax.new(
|
3405
|
+
node: block_params,
|
3406
|
+
message: "Unsupported block params pattern, probably masgn?"
|
3196
3407
|
)
|
3197
3408
|
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3409
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3410
|
+
constraints.solution(checker, variables: type_param_names, context: ccontext)
|
3411
|
+
}
|
3412
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3201
3413
|
|
3202
|
-
|
3203
|
-
Array.new(method_type.free_variables.size, AST::Builtin.any_type))
|
3204
|
-
method_type = method_type.subst(s)
|
3414
|
+
return_type = method_type.type.return_type
|
3205
3415
|
end
|
3206
3416
|
else
|
3207
|
-
|
3208
|
-
|
3209
|
-
|
3210
|
-
|
3417
|
+
# Block is given but method doesn't accept
|
3418
|
+
#
|
3419
|
+
constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
|
3420
|
+
errors << error
|
3421
|
+
end
|
3211
3422
|
|
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
|
3423
|
+
errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
|
3424
|
+
node: node,
|
3425
|
+
method_type: method_type
|
3219
3426
|
)
|
3220
|
-
|
3427
|
+
|
3428
|
+
method_type = eliminate_vars(method_type, type_param_names)
|
3429
|
+
return_type = method_type.type.return_type
|
3221
3430
|
end
|
3222
3431
|
else
|
3223
|
-
# Block is given
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3432
|
+
# Block syntax is not given
|
3433
|
+
arg = args.block_pass_arg
|
3434
|
+
|
3435
|
+
case
|
3436
|
+
when arg.compatible?
|
3437
|
+
if arg.node
|
3438
|
+
# Block pass (&block) is given
|
3439
|
+
node_type, constr = constr.synthesize(arg.node, hint: arg.node_type)
|
3440
|
+
|
3441
|
+
nil_given =
|
3442
|
+
constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success? &&
|
3443
|
+
!node_type.is_a?(AST::Types::Any)
|
3444
|
+
|
3445
|
+
if nil_given
|
3446
|
+
# nil is given ==> no block arg node is given
|
3447
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3448
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3449
|
+
}
|
3450
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3228
3451
|
|
3229
|
-
|
3230
|
-
|
3231
|
-
|
3232
|
-
|
3233
|
-
|
3234
|
-
|
3235
|
-
|
3452
|
+
# Passing no block
|
3453
|
+
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3454
|
+
node: node,
|
3455
|
+
method_type: method_type
|
3456
|
+
)
|
3457
|
+
else
|
3458
|
+
# non-nil value is given
|
3459
|
+
constr.check_relation(sub_type: node_type, super_type: arg.node_type, constraints: constraints).else do |result|
|
3460
|
+
errors << Diagnostic::Ruby::BlockTypeMismatch.new(
|
3461
|
+
node: arg.node,
|
3462
|
+
expected: arg.node_type,
|
3463
|
+
actual: node_type,
|
3464
|
+
result: result
|
3465
|
+
)
|
3466
|
+
end
|
3236
3467
|
|
3237
|
-
|
3238
|
-
|
3239
|
-
|
3240
|
-
|
3241
|
-
|
3242
|
-
|
3243
|
-
|
3244
|
-
|
3245
|
-
|
3246
|
-
|
3247
|
-
|
3468
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3469
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3470
|
+
}
|
3471
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3472
|
+
end
|
3473
|
+
else
|
3474
|
+
# Block is not given
|
3475
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3476
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3477
|
+
}
|
3478
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3479
|
+
end
|
3248
3480
|
|
3249
|
-
|
3481
|
+
return_type = method_type.type.return_type
|
3250
3482
|
|
3251
|
-
|
3252
|
-
|
3253
|
-
|
3254
|
-
|
3483
|
+
when arg.block_missing?
|
3484
|
+
# Block is required but not given
|
3485
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3486
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3487
|
+
}
|
3255
3488
|
|
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
|
3489
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3490
|
+
return_type = method_type.type.return_type
|
3266
3491
|
|
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
|
3492
|
+
errors << Diagnostic::Ruby::RequiredBlockMissing.new(
|
3493
|
+
node: node,
|
3494
|
+
method_type: method_type
|
3274
3495
|
)
|
3275
3496
|
|
3276
|
-
|
3497
|
+
when arg.unexpected_block?
|
3498
|
+
# Unexpected block is given
|
3499
|
+
method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
|
3500
|
+
constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
|
3501
|
+
}
|
3502
|
+
method_type = eliminate_vars(method_type, type_param_names) unless solved
|
3503
|
+
return_type = method_type.type.return_type
|
3277
3504
|
|
3278
|
-
|
3279
|
-
|
3280
|
-
|
3505
|
+
node_type, constr = constr.synthesize(arg.node)
|
3506
|
+
|
3507
|
+
unless constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success?
|
3508
|
+
errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
|
3281
3509
|
node: node,
|
3282
3510
|
method_type: method_type
|
3283
3511
|
)
|
3284
3512
|
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
3513
|
end
|
3335
3514
|
end
|
3336
|
-
end
|
3337
|
-
|
3338
|
-
call = if errors.empty?
|
3339
|
-
TypeInference::MethodCall::Typed.new(
|
3340
|
-
node: node,
|
3341
|
-
context: context.method_context,
|
3342
|
-
receiver_type: receiver_type,
|
3343
|
-
method_name: method_name,
|
3344
|
-
actual_method_type: method_type,
|
3345
|
-
return_type: return_type || method_type.type.return_type,
|
3346
|
-
method_decls: method_type.method_decls
|
3347
|
-
)
|
3348
|
-
else
|
3349
|
-
TypeInference::MethodCall::Error.new(
|
3350
|
-
node: node,
|
3351
|
-
context: context.method_context,
|
3352
|
-
receiver_type: receiver_type,
|
3353
|
-
method_name: method_name,
|
3354
|
-
return_type: return_type || method_type.type.return_type,
|
3355
|
-
method_decls: method_type.method_decls,
|
3356
|
-
errors: errors
|
3357
|
-
)
|
3358
|
-
end
|
3359
3515
|
|
3360
|
-
|
3361
|
-
|
3362
|
-
|
3363
|
-
|
3516
|
+
call = if errors.empty?
|
3517
|
+
TypeInference::MethodCall::Typed.new(
|
3518
|
+
node: node,
|
3519
|
+
context: context.method_context,
|
3520
|
+
receiver_type: receiver_type,
|
3521
|
+
method_name: method_name,
|
3522
|
+
actual_method_type: method_type,
|
3523
|
+
return_type: return_type || method_type.type.return_type,
|
3524
|
+
method_decls: method_type.method_decls
|
3525
|
+
)
|
3526
|
+
else
|
3527
|
+
TypeInference::MethodCall::Error.new(
|
3528
|
+
node: node,
|
3529
|
+
context: context.method_context,
|
3530
|
+
receiver_type: receiver_type,
|
3531
|
+
method_name: method_name,
|
3532
|
+
return_type: return_type || method_type.type.return_type,
|
3533
|
+
method_decls: method_type.method_decls,
|
3534
|
+
errors: errors
|
3535
|
+
)
|
3536
|
+
end
|
3537
|
+
|
3538
|
+
[
|
3539
|
+
call,
|
3540
|
+
constr
|
3541
|
+
]
|
3542
|
+
end
|
3364
3543
|
end
|
3365
3544
|
|
3366
3545
|
def type_check_argument(node, receiver_type:, type:, constraints:, report_node: node, errors:)
|
@@ -3383,13 +3562,14 @@ module Steep
|
|
3383
3562
|
message: "Unsupported block params pattern, probably masgn?"
|
3384
3563
|
)
|
3385
3564
|
)
|
3386
|
-
block_params = TypeInference::BlockParams.new(leading_params: [], optional_params: [], rest_param: nil, trailing_params: [])
|
3565
|
+
block_params = TypeInference::BlockParams.new(leading_params: [], optional_params: [], rest_param: nil, trailing_params: [], block_param: nil)
|
3387
3566
|
end
|
3388
3567
|
|
3389
3568
|
block_constr = for_block(
|
3390
3569
|
block_params: block_params,
|
3391
3570
|
block_param_hint: nil,
|
3392
3571
|
block_type_hint: AST::Builtin.any_type,
|
3572
|
+
block_block_hint: nil,
|
3393
3573
|
block_annotations: block_annotations,
|
3394
3574
|
node_type_hint: AST::Builtin.any_type
|
3395
3575
|
)
|
@@ -3416,8 +3596,8 @@ module Steep
|
|
3416
3596
|
end
|
3417
3597
|
end
|
3418
3598
|
|
3419
|
-
def for_block(block_params:, block_param_hint:, block_type_hint:, block_annotations:, node_type_hint:)
|
3420
|
-
block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
|
3599
|
+
def for_block(block_params:, block_param_hint:, block_type_hint:, block_block_hint:, block_annotations:, node_type_hint:)
|
3600
|
+
block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint)
|
3421
3601
|
|
3422
3602
|
param_types_hash = {}
|
3423
3603
|
if block_param_pairs
|
@@ -3485,7 +3665,8 @@ module Steep
|
|
3485
3665
|
self_type: self_type,
|
3486
3666
|
type_env: type_env.dup,
|
3487
3667
|
lvar_env: lvar_env,
|
3488
|
-
call_context: self.context.call_context
|
3668
|
+
call_context: self.context.call_context,
|
3669
|
+
variable_context: variable_context
|
3489
3670
|
)
|
3490
3671
|
)
|
3491
3672
|
end
|