steep 0.33.0 → 0.34.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 +7 -0
- data/lib/steep.rb +3 -0
- data/lib/steep/annotation_parser.rb +1 -1
- data/lib/steep/ast/types/factory.rb +63 -57
- data/lib/steep/cli.rb +14 -1
- data/lib/steep/drivers/stats.rb +85 -0
- data/lib/steep/errors.rb +19 -15
- data/lib/steep/interface/method_type.rb +12 -23
- data/lib/steep/method_name.rb +28 -0
- data/lib/steep/project/completion_provider.rb +24 -15
- data/lib/steep/project/source_file.rb +2 -1
- data/lib/steep/server/interaction_worker.rb +1 -1
- data/lib/steep/subtyping/variable_occurrence.rb +2 -0
- data/lib/steep/type_construction.rb +577 -415
- data/lib/steep/type_inference/context.rb +7 -3
- data/lib/steep/type_inference/local_variable_type_env.rb +10 -1
- data/lib/steep/type_inference/method_call.rb +116 -0
- data/lib/steep/typing.rb +38 -8
- data/lib/steep/version.rb +1 -1
- data/smoke/regression/range.rb +5 -0
- data/steep.gemspec +1 -1
- metadata +8 -4
@@ -774,16 +774,14 @@ module Steep
|
|
774
774
|
attr_reader :params
|
775
775
|
attr_reader :block
|
776
776
|
attr_reader :return_type
|
777
|
-
attr_reader :
|
778
|
-
attr_reader :method_def
|
777
|
+
attr_reader :method_decls
|
779
778
|
|
780
|
-
def initialize(type_params:, params:, block:, return_type:,
|
779
|
+
def initialize(type_params:, params:, block:, return_type:, method_decls:)
|
781
780
|
@type_params = type_params
|
782
781
|
@params = params
|
783
782
|
@block = block
|
784
783
|
@return_type = return_type
|
785
|
-
@
|
786
|
-
@method_def = method_def
|
784
|
+
@method_decls = method_decls
|
787
785
|
end
|
788
786
|
|
789
787
|
def ==(other)
|
@@ -791,9 +789,7 @@ module Steep
|
|
791
789
|
other.type_params == type_params &&
|
792
790
|
other.params == params &&
|
793
791
|
other.block == block &&
|
794
|
-
other.return_type == return_type
|
795
|
-
(!other.method_def || !method_def || other.method_def == method_def) &&
|
796
|
-
(!other.location || !location || other.location == location)
|
792
|
+
other.return_type == return_type
|
797
793
|
end
|
798
794
|
|
799
795
|
alias eql? ==
|
@@ -824,8 +820,7 @@ module Steep
|
|
824
820
|
params: params.subst(s_),
|
825
821
|
block: block&.subst(s_),
|
826
822
|
return_type: return_type.subst(s_),
|
827
|
-
|
828
|
-
location: location
|
823
|
+
method_decls: method_decls
|
829
824
|
)
|
830
825
|
end
|
831
826
|
|
@@ -847,17 +842,15 @@ module Steep
|
|
847
842
|
params: params.subst(s),
|
848
843
|
block: block&.subst(s),
|
849
844
|
return_type: return_type.subst(s),
|
850
|
-
|
851
|
-
method_def: method_def)
|
845
|
+
method_decls: method_decls)
|
852
846
|
end
|
853
847
|
|
854
|
-
def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type,
|
848
|
+
def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type, method_decls: self.method_decls)
|
855
849
|
self.class.new(type_params: type_params,
|
856
850
|
params: params,
|
857
851
|
block: block,
|
858
852
|
return_type: return_type,
|
859
|
-
|
860
|
-
location: location)
|
853
|
+
method_decls: method_decls)
|
861
854
|
end
|
862
855
|
|
863
856
|
def to_s
|
@@ -873,8 +866,7 @@ module Steep
|
|
873
866
|
params: params.map_type(&block),
|
874
867
|
block: self.block&.yield_self {|blk| blk.map_type(&block) },
|
875
868
|
return_type: yield(return_type),
|
876
|
-
|
877
|
-
method_def: method_def)
|
869
|
+
method_decls: method_decls)
|
878
870
|
end
|
879
871
|
|
880
872
|
# Returns a new method type which can be used for the method implementation type of both `self` and `other`.
|
@@ -902,8 +894,7 @@ module Steep
|
|
902
894
|
return_type: AST::Types::Union.build(
|
903
895
|
types: [return_type.subst(s1),other.return_type.subst(s2)]
|
904
896
|
),
|
905
|
-
|
906
|
-
location: nil
|
897
|
+
method_decls: method_decls + other.method_decls
|
907
898
|
)
|
908
899
|
end
|
909
900
|
|
@@ -958,8 +949,7 @@ module Steep
|
|
958
949
|
block: block,
|
959
950
|
return_type: return_type,
|
960
951
|
type_params: type_params,
|
961
|
-
|
962
|
-
location: nil
|
952
|
+
method_decls: method_decls + other.method_decls
|
963
953
|
)
|
964
954
|
end
|
965
955
|
|
@@ -1006,8 +996,7 @@ module Steep
|
|
1006
996
|
block: block,
|
1007
997
|
return_type: return_type,
|
1008
998
|
type_params: type_params,
|
1009
|
-
|
1010
|
-
location: nil
|
999
|
+
method_decls: method_decls + other.method_decls
|
1011
1000
|
)
|
1012
1001
|
end
|
1013
1002
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Steep
|
2
|
+
InstanceMethodName = Struct.new(:type_name, :method_name, keyword_init: true) do
|
3
|
+
def to_s
|
4
|
+
"#{type_name}##{method_name}"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
SingletonMethodName = Struct.new(:type_name, :method_name, keyword_init: true) do
|
9
|
+
def to_s
|
10
|
+
"#{type_name}.#{method_name}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ::Kernel
|
15
|
+
def MethodName(string)
|
16
|
+
case string
|
17
|
+
when /#/
|
18
|
+
type_name, method_name = string.split(/#/, 2)
|
19
|
+
InstanceMethodName.new(type_name: TypeName(type_name), method_name: method_name.to_sym)
|
20
|
+
when /\./
|
21
|
+
type_name, method_name = string.split(/\./, 2)
|
22
|
+
SingletonMethodName.new(type_name: TypeName(type_name), method_name: method_name.to_sym)
|
23
|
+
else
|
24
|
+
raise "Unexpected method name: #{string}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -10,9 +10,27 @@ module Steep
|
|
10
10
|
|
11
11
|
InstanceVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
|
12
12
|
LocalVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
|
13
|
-
MethodNameItem = Struct.new(:identifier, :range, :
|
13
|
+
MethodNameItem = Struct.new(:identifier, :range, :receiver_type, :method_type, :method_decls, keyword_init: true) do
|
14
14
|
def comment
|
15
|
-
|
15
|
+
case method_decls.size
|
16
|
+
when 0
|
17
|
+
nil
|
18
|
+
when 1
|
19
|
+
method_decls.to_a.first.method_def&.comment
|
20
|
+
else
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def inherited?
|
26
|
+
case receiver_type
|
27
|
+
when AST::Types::Name::Instance, AST::Types::Name::Singleton, AST::Types::Name::Interface
|
28
|
+
method_decls.any? do |decl|
|
29
|
+
decl.method_name.type_name != receiver_type.name
|
30
|
+
end
|
31
|
+
else
|
32
|
+
false
|
33
|
+
end
|
16
34
|
end
|
17
35
|
end
|
18
36
|
|
@@ -245,15 +263,15 @@ module Steep
|
|
245
263
|
items << MethodNameItem.new(
|
246
264
|
identifier: name,
|
247
265
|
range: range,
|
248
|
-
|
249
|
-
method_type:
|
250
|
-
|
266
|
+
receiver_type: type,
|
267
|
+
method_type: subtyping.factory.method_type_1(method_type, self_type: type),
|
268
|
+
method_decls: method_type.method_decls
|
251
269
|
)
|
252
270
|
end
|
253
271
|
end
|
254
272
|
end
|
255
273
|
end
|
256
|
-
rescue
|
274
|
+
rescue RuntimeError => exn
|
257
275
|
# nop
|
258
276
|
end
|
259
277
|
|
@@ -298,15 +316,6 @@ module Steep
|
|
298
316
|
index
|
299
317
|
end
|
300
318
|
|
301
|
-
def inherited_method?(method_def, type)
|
302
|
-
case type
|
303
|
-
when AST::Types::Name::Instance, AST::Types::Name::Singleton, AST::Types::Name::Interface
|
304
|
-
method_def.implemented_in != type.name
|
305
|
-
else
|
306
|
-
false
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
319
|
def disallowed_method?(name)
|
311
320
|
# initialize isn't invoked by developers when creating
|
312
321
|
# instances of new classes, so don't show it as
|
@@ -66,7 +66,8 @@ module Steep
|
|
66
66
|
break_context: nil,
|
67
67
|
self_type: AST::Builtin::Object.instance_type,
|
68
68
|
type_env: type_env,
|
69
|
-
lvar_env: lvar_env
|
69
|
+
lvar_env: lvar_env,
|
70
|
+
call_context: TypeInference::MethodCall::TopLevelContext.new
|
70
71
|
)
|
71
72
|
|
72
73
|
typing = Typing.new(source: source, root_context: context)
|
@@ -196,7 +196,7 @@ HOVER
|
|
196
196
|
),
|
197
197
|
documentation: item.comment&.string,
|
198
198
|
insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET,
|
199
|
-
sort_text: item.
|
199
|
+
sort_text: item.inherited? ? 'z' : 'a' # Ensure language server puts non-inherited methods before inherited methods
|
200
200
|
)
|
201
201
|
when Project::CompletionProvider::InstanceVariableItem
|
202
202
|
label = "#{item.identifier}: #{item.type}"
|
@@ -131,7 +131,7 @@ module Steep
|
|
131
131
|
definition_method_type = if definition
|
132
132
|
definition.methods[method_name]&.yield_self do |method|
|
133
133
|
method.method_types
|
134
|
-
.map {|method_type| checker.factory.method_type(method_type, self_type: self_type) }
|
134
|
+
.map {|method_type| checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]) }
|
135
135
|
.select {|method_type| method_type.is_a?(Interface::MethodType) }
|
136
136
|
.inject {|t1, t2| t1 + t2}
|
137
137
|
end
|
@@ -216,6 +216,21 @@ module Steep
|
|
216
216
|
|
217
217
|
lvar_env = lvar_env.annotate(annots)
|
218
218
|
|
219
|
+
call_context = case self_type
|
220
|
+
when nil
|
221
|
+
TypeInference::MethodCall::UnknownContext.new()
|
222
|
+
when AST::Types::Name::Singleton
|
223
|
+
TypeInference::MethodCall::MethodContext.new(
|
224
|
+
method_name: SingletonMethodName.new(type_name: module_context.class_name, method_name: method_name)
|
225
|
+
)
|
226
|
+
when AST::Types::Name::Instance, AST::Types::Intersection
|
227
|
+
TypeInference::MethodCall::MethodContext.new(
|
228
|
+
method_name: InstanceMethodName.new(type_name: module_context.class_name, method_name: method_name)
|
229
|
+
)
|
230
|
+
else
|
231
|
+
raise "Unexpected self_type: #{self_type}"
|
232
|
+
end
|
233
|
+
|
219
234
|
self.class.new(
|
220
235
|
checker: checker,
|
221
236
|
source: source,
|
@@ -227,7 +242,8 @@ module Steep
|
|
227
242
|
break_context: nil,
|
228
243
|
self_type: annots.self_type || self_type,
|
229
244
|
type_env: type_env,
|
230
|
-
lvar_env: lvar_env
|
245
|
+
lvar_env: lvar_env,
|
246
|
+
call_context: call_context
|
231
247
|
),
|
232
248
|
typing: typing,
|
233
249
|
)
|
@@ -355,7 +371,8 @@ module Steep
|
|
355
371
|
module_context: module_context_,
|
356
372
|
self_type: module_context_.module_type,
|
357
373
|
type_env: module_type_env,
|
358
|
-
lvar_env: lvar_env
|
374
|
+
lvar_env: lvar_env,
|
375
|
+
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context_.class_name)
|
359
376
|
)
|
360
377
|
)
|
361
378
|
end
|
@@ -424,7 +441,8 @@ module Steep
|
|
424
441
|
break_context: nil,
|
425
442
|
self_type: module_context.module_type,
|
426
443
|
type_env: class_type_env,
|
427
|
-
lvar_env: lvar_env
|
444
|
+
lvar_env: lvar_env,
|
445
|
+
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name)
|
428
446
|
)
|
429
447
|
|
430
448
|
self.class.new(
|
@@ -509,7 +527,8 @@ module Steep
|
|
509
527
|
break_context: nil,
|
510
528
|
self_type: module_context.module_type,
|
511
529
|
type_env: type_env,
|
512
|
-
lvar_env: lvar_env
|
530
|
+
lvar_env: lvar_env,
|
531
|
+
call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name)
|
513
532
|
)
|
514
533
|
|
515
534
|
self.class.new(
|
@@ -608,6 +627,22 @@ module Steep
|
|
608
627
|
Pair.new(type: type, constr: constr)
|
609
628
|
end
|
610
629
|
|
630
|
+
def add_call(call)
|
631
|
+
case call
|
632
|
+
when TypeInference::MethodCall::NoMethodError
|
633
|
+
typing.add_error(call.error)
|
634
|
+
when TypeInference::MethodCall::Error
|
635
|
+
call.errors.each do |error|
|
636
|
+
typing.add_error(error)
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
typing.add_typing(call.node, call.return_type, nil)
|
641
|
+
typing.add_call(call.node, call)
|
642
|
+
|
643
|
+
Pair.new(type: call.return_type, constr: self)
|
644
|
+
end
|
645
|
+
|
611
646
|
def synthesize(node, hint: nil)
|
612
647
|
Steep.logger.tagged "synthesize:(#{node.location.expression.to_s.split(/:/, 2).last})" do
|
613
648
|
Steep.logger.debug node.type
|
@@ -786,28 +821,33 @@ module Steep
|
|
786
821
|
when :super
|
787
822
|
yield_self do
|
788
823
|
if self_type && method_context&.method
|
789
|
-
if method_context.super_method
|
824
|
+
if super_def = method_context.super_method
|
790
825
|
each_child_node(node) do |child|
|
791
826
|
synthesize(child)
|
792
827
|
end
|
793
828
|
|
794
829
|
super_method = Interface::Interface::Entry.new(
|
795
830
|
method_types: method_context.super_method.method_types.map {|method_type|
|
796
|
-
|
831
|
+
decl = TypeInference::MethodCall::MethodDecl.new(
|
832
|
+
method_name: InstanceMethodName.new(type_name: super_def.implemented_in || super_def.defined_in,
|
833
|
+
method_name: method_context.name),
|
834
|
+
method_def: super_def
|
835
|
+
)
|
836
|
+
checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[decl])
|
797
837
|
}
|
798
838
|
)
|
799
839
|
args = TypeInference::SendArgs.from_nodes(node.children.dup)
|
800
840
|
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
841
|
+
call, constr = type_method_call(node,
|
842
|
+
receiver_type: self_type,
|
843
|
+
method_name: method_context.name,
|
844
|
+
method: super_method,
|
845
|
+
args: args,
|
846
|
+
block_params: nil,
|
847
|
+
block_body: nil,
|
848
|
+
topdown_hint: true)
|
809
849
|
|
810
|
-
|
850
|
+
constr.add_call(call)
|
811
851
|
else
|
812
852
|
fallback_to_any node do
|
813
853
|
Errors::UnexpectedSuper.new(node: node, method: method_context.name)
|
@@ -1208,7 +1248,13 @@ module Steep
|
|
1208
1248
|
|
1209
1249
|
when :class
|
1210
1250
|
yield_self do
|
1211
|
-
|
1251
|
+
constr = self
|
1252
|
+
|
1253
|
+
name, sup, _ = node.children
|
1254
|
+
_, constr = constr.synthesize(name)
|
1255
|
+
_, constr = constr.synthesize(sup) if sup
|
1256
|
+
|
1257
|
+
constr.for_class(node).tap do |constructor|
|
1212
1258
|
constructor.typing.add_context_for_node(node, context: constructor.context)
|
1213
1259
|
constructor.typing.add_context_for_body(node, context: constructor.context)
|
1214
1260
|
|
@@ -1224,6 +1270,11 @@ module Steep
|
|
1224
1270
|
|
1225
1271
|
when :module
|
1226
1272
|
yield_self do
|
1273
|
+
constr = self
|
1274
|
+
|
1275
|
+
name, _ = node.children
|
1276
|
+
_, constr = constr.synthesize(name)
|
1277
|
+
|
1227
1278
|
for_module(node).yield_self do |constructor|
|
1228
1279
|
constructor.typing.add_context_for_node(node, context: constructor.context)
|
1229
1280
|
constructor.typing.add_context_for_body(node, context: constructor.context)
|
@@ -1271,24 +1322,39 @@ module Steep
|
|
1271
1322
|
when :self
|
1272
1323
|
add_typing node, type: AST::Types::Self.new
|
1273
1324
|
|
1325
|
+
when :cbase
|
1326
|
+
add_typing node, type: AST::Types::Void.new
|
1327
|
+
|
1274
1328
|
when :const
|
1275
|
-
|
1329
|
+
parent = node.children[0]
|
1330
|
+
if parent
|
1331
|
+
_, constr = synthesize(parent)
|
1332
|
+
else
|
1333
|
+
constr = self
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
const_name = constr.module_name_from_node(node)
|
1276
1337
|
|
1277
1338
|
if const_name
|
1278
1339
|
type = type_env.get(const: const_name) do
|
1279
|
-
fallback_to_any
|
1340
|
+
constr.fallback_to_any(node)
|
1280
1341
|
end
|
1281
|
-
add_typing
|
1342
|
+
constr.add_typing(node, type: type)
|
1282
1343
|
else
|
1283
|
-
fallback_to_any
|
1344
|
+
constr.fallback_to_any(node)
|
1284
1345
|
end
|
1285
1346
|
|
1286
1347
|
when :casgn
|
1287
1348
|
yield_self do
|
1288
|
-
|
1349
|
+
constr = self
|
1350
|
+
|
1351
|
+
parent = node.children[0]
|
1352
|
+
_, constr = constr.synthesize(parent) if parent
|
1353
|
+
const_name = constr.module_name_from_node(node)
|
1354
|
+
|
1289
1355
|
if const_name
|
1290
1356
|
const_type = type_env.get(const: const_name) {}
|
1291
|
-
value_type = synthesize(node.children.last, hint: const_type)
|
1357
|
+
value_type, constr = constr.synthesize(node.children.last, hint: const_type)
|
1292
1358
|
type = type_env.assign(const: const_name, type: value_type, self_type: self_type) do |error|
|
1293
1359
|
case error
|
1294
1360
|
when Subtyping::Result::Failure
|
@@ -1302,10 +1368,10 @@ module Steep
|
|
1302
1368
|
end
|
1303
1369
|
end
|
1304
1370
|
|
1305
|
-
add_typing(node, type: type)
|
1371
|
+
constr.add_typing(node, type: type)
|
1306
1372
|
else
|
1307
|
-
synthesize(node.children.last)
|
1308
|
-
fallback_to_any(node)
|
1373
|
+
_, constr = constr.synthesize(node.children.last)
|
1374
|
+
constr.fallback_to_any(node)
|
1309
1375
|
end
|
1310
1376
|
end
|
1311
1377
|
|
@@ -1338,7 +1404,7 @@ module Steep
|
|
1338
1404
|
if method_context&.method
|
1339
1405
|
if method_context.super_method
|
1340
1406
|
types = method_context.super_method.method_types.map {|method_type|
|
1341
|
-
checker.factory.method_type(method_type, self_type: self_type).return_type
|
1407
|
+
checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]).return_type
|
1342
1408
|
}
|
1343
1409
|
add_typing(node, type: union_type(*types))
|
1344
1410
|
else
|
@@ -2029,7 +2095,7 @@ module Steep
|
|
2029
2095
|
unless pair.is_a?(Pair) && !pair.type.is_a?(Pair)
|
2030
2096
|
# Steep.logger.error { "result = #{pair.inspect}" }
|
2031
2097
|
# Steep.logger.error { "node = #{node.type}" }
|
2032
|
-
raise "#synthesize should return an instance of Pair: #{pair.class}"
|
2098
|
+
raise "#synthesize should return an instance of Pair: #{pair.class}, node=#{node.inspect}"
|
2033
2099
|
end
|
2034
2100
|
end
|
2035
2101
|
end
|
@@ -2273,177 +2339,222 @@ module Steep
|
|
2273
2339
|
return_hint = type_hint.return_type
|
2274
2340
|
end
|
2275
2341
|
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
block_annotations: block_annotations,
|
2283
|
-
topdown_hint: true)
|
2342
|
+
block_constr = for_block(
|
2343
|
+
block_params: params,
|
2344
|
+
block_param_hint: params_hint,
|
2345
|
+
block_annotations: block_annotations,
|
2346
|
+
node_type_hint: nil
|
2347
|
+
)
|
2284
2348
|
|
2285
|
-
|
2286
|
-
end
|
2349
|
+
block_constr.typing.add_context_for_body(node, context: block_constr.context)
|
2287
2350
|
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2351
|
+
params.params.each do |param|
|
2352
|
+
_, block_constr = block_constr.synthesize(param.node, hint: param.type)
|
2353
|
+
end
|
2291
2354
|
|
2292
|
-
if
|
2293
|
-
|
2355
|
+
if block_body
|
2356
|
+
return_type = block_constr.synthesize_block(
|
2357
|
+
node: node,
|
2358
|
+
block_body: block_body,
|
2359
|
+
topdown_hint: true,
|
2360
|
+
block_type_hint: return_hint
|
2361
|
+
) do |error|
|
2362
|
+
typing.add_error(error)
|
2363
|
+
end
|
2364
|
+
else
|
2365
|
+
return_type = AST::Builtin.any_type
|
2294
2366
|
end
|
2295
2367
|
|
2296
|
-
|
2368
|
+
block_type = AST::Types::Proc.new(
|
2369
|
+
params: params_hint || params.params_type,
|
2370
|
+
return_type: return_type
|
2371
|
+
)
|
2297
2372
|
|
2298
|
-
|
2299
|
-
|
2300
|
-
each_child_node(send_node) do |child|
|
2301
|
-
unless child.equal?(receiver)
|
2302
|
-
_, constr = constr.synthesize(child)
|
2303
|
-
end
|
2304
|
-
end
|
2373
|
+
add_typing node, type: block_type
|
2374
|
+
end
|
2305
2375
|
|
2306
|
-
|
2376
|
+
def synthesize_children(node, skips: [])
|
2377
|
+
skips = Set.new.compare_by_identity.merge(skips)
|
2307
2378
|
|
2308
|
-
|
2309
|
-
fallback_to_any node
|
2379
|
+
constr = self
|
2310
2380
|
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2381
|
+
each_child_node(node) do |child|
|
2382
|
+
unless skips.include?(child)
|
2383
|
+
_, constr = constr.synthesize(child)
|
2384
|
+
end
|
2385
|
+
end
|
2315
2386
|
|
2316
|
-
|
2317
|
-
|
2318
|
-
when AST::Types::Self
|
2319
|
-
Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
|
2320
|
-
fallback_to_any node do
|
2321
|
-
Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2322
|
-
end
|
2323
|
-
else
|
2324
|
-
begin
|
2325
|
-
interface = checker.factory.interface(receiver_type,
|
2326
|
-
private: !receiver,
|
2327
|
-
self_type: expanded_receiver_type)
|
2328
|
-
|
2329
|
-
method = interface.methods[method_name]
|
2330
|
-
|
2331
|
-
if method
|
2332
|
-
args = TypeInference::SendArgs.from_nodes(arguments)
|
2333
|
-
return_type, constr, _ = constr.type_method_call(node,
|
2334
|
-
method: method,
|
2335
|
-
method_name: method_name,
|
2336
|
-
args: args,
|
2337
|
-
block_params: block_params,
|
2338
|
-
block_body: block_body,
|
2339
|
-
receiver_type: receiver_type,
|
2340
|
-
topdown_hint: true)
|
2341
|
-
|
2342
|
-
add_typing node, type: return_type, constr: constr
|
2343
|
-
else
|
2344
|
-
fallback_to_any node do
|
2345
|
-
Errors::NoMethod.new(node: node, method: method_name, type: expanded_receiver_type)
|
2346
|
-
end
|
2347
|
-
end
|
2348
|
-
rescue => exn
|
2349
|
-
case exn
|
2350
|
-
when RBS::NoTypeFoundError, RBS::NoMixinFoundError, RBS::NoSuperclassFoundError, RBS::InvalidTypeApplicationError
|
2351
|
-
# ignore known RBS errors.
|
2352
|
-
else
|
2353
|
-
Steep.log_error(exn, message: "Unexpected error in #type_send: #{exn.message} (#{exn.class})")
|
2354
|
-
end
|
2387
|
+
constr
|
2388
|
+
end
|
2355
2389
|
|
2356
|
-
|
2357
|
-
|
2358
|
-
end
|
2359
|
-
end
|
2360
|
-
end
|
2361
|
-
end
|
2390
|
+
def type_send_interface(node, interface:, receiver:, receiver_type:, method_name:, arguments:, block_params:, block_body:)
|
2391
|
+
method = interface.methods[method_name]
|
2362
2392
|
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2393
|
+
if method
|
2394
|
+
args = TypeInference::SendArgs.from_nodes(arguments)
|
2395
|
+
call, constr = type_method_call(node,
|
2396
|
+
method: method,
|
2397
|
+
method_name: method_name,
|
2398
|
+
args: args,
|
2399
|
+
block_params: block_params,
|
2400
|
+
block_body: block_body,
|
2401
|
+
receiver_type: receiver_type,
|
2402
|
+
topdown_hint: true)
|
2403
|
+
|
2404
|
+
if call && constr
|
2405
|
+
case method_name.to_s
|
2406
|
+
when "[]=", /\w=\Z/
|
2407
|
+
if typing.has_type?(arguments.last)
|
2408
|
+
call = call.with_return_type(typing.type_of(node: arguments.last))
|
2372
2409
|
end
|
2373
2410
|
end
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2411
|
+
else
|
2412
|
+
error = Errors::UnresolvedOverloading.new(
|
2413
|
+
node: node,
|
2414
|
+
receiver_type: receiver_type,
|
2415
|
+
method_name: method_name,
|
2416
|
+
method_types: method.method_types
|
2417
|
+
)
|
2418
|
+
call = TypeInference::MethodCall::Error.new(
|
2419
|
+
node: node,
|
2420
|
+
context: context.method_context,
|
2421
|
+
method_name: method_name,
|
2422
|
+
receiver_type: receiver_type,
|
2423
|
+
errors: [error]
|
2424
|
+
)
|
2386
2425
|
|
2387
|
-
|
2426
|
+
constr = synthesize_children(node, skips: [receiver])
|
2427
|
+
if block_params
|
2428
|
+
block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
2388
2429
|
|
2389
|
-
|
2430
|
+
constr.type_block_without_hint(
|
2431
|
+
node: node,
|
2432
|
+
block_params: TypeInference::BlockParams.from_node(block_params, annotations: block_annotations),
|
2433
|
+
block_annotations: block_annotations,
|
2434
|
+
block_body: block_body
|
2435
|
+
) do |error|
|
2436
|
+
errors << error
|
2437
|
+
end
|
2390
2438
|
end
|
2391
2439
|
end
|
2440
|
+
|
2441
|
+
constr.add_call(call)
|
2392
2442
|
else
|
2393
|
-
|
2443
|
+
add_call(
|
2444
|
+
TypeInference::MethodCall::NoMethodError.new(
|
2445
|
+
node: node,
|
2446
|
+
context: context.method_context,
|
2447
|
+
method_name: method_name,
|
2448
|
+
receiver_type: receiver_type,
|
2449
|
+
error: Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2450
|
+
)
|
2451
|
+
)
|
2394
2452
|
end
|
2395
2453
|
end
|
2396
2454
|
|
2397
|
-
def
|
2398
|
-
|
2399
|
-
|
2400
|
-
if param.type
|
2401
|
-
env.set(lvar: param.var.name, type: param.type)
|
2402
|
-
else
|
2403
|
-
env.set(lvar: param.var.name, type: type)
|
2404
|
-
end
|
2405
|
-
end
|
2455
|
+
def type_send(node, send_node:, block_params:, block_body:, unwrap: false)
|
2456
|
+
receiver, method_name, *arguments = send_node.children
|
2457
|
+
recv_type, constr = receiver ? synthesize(receiver) : [AST::Types::Self.new, self]
|
2406
2458
|
|
2407
|
-
|
2408
|
-
|
2409
|
-
ivar_types: block_annotations.ivar_types,
|
2410
|
-
const_types: block_annotations.const_types,
|
2411
|
-
)
|
2459
|
+
if unwrap
|
2460
|
+
recv_type = unwrap(recv_type)
|
2412
2461
|
end
|
2413
2462
|
|
2414
|
-
|
2463
|
+
receiver_type = checker.factory.deep_expand_alias(recv_type)
|
2415
2464
|
|
2416
|
-
|
2417
|
-
|
2418
|
-
|
2419
|
-
method_return_type
|
2420
|
-
end
|
2421
|
-
Steep.logger.debug("return_type = #{return_type}")
|
2465
|
+
type, constr = case receiver_type
|
2466
|
+
when nil
|
2467
|
+
raise
|
2422
2468
|
|
2423
|
-
|
2424
|
-
|
2469
|
+
when AST::Types::Any
|
2470
|
+
constr = constr.synthesize_children(node, skips: [receiver])
|
2471
|
+
constr.add_call(
|
2472
|
+
TypeInference::MethodCall::Untyped.new(
|
2473
|
+
node: node,
|
2474
|
+
context: context.method_context,
|
2475
|
+
method_name: method_name
|
2476
|
+
)
|
2477
|
+
)
|
2425
2478
|
|
2426
|
-
|
2427
|
-
|
2428
|
-
|
2429
|
-
|
2430
|
-
|
2479
|
+
when AST::Types::Void, AST::Types::Bot, AST::Types::Top, AST::Types::Var
|
2480
|
+
constr = constr.synthesize_children(node, skips: [receiver])
|
2481
|
+
constr.add_call(
|
2482
|
+
TypeInference::MethodCall::NoMethodError.new(
|
2483
|
+
node: node,
|
2484
|
+
context: context.method_context,
|
2485
|
+
method_name: method_name,
|
2486
|
+
receiver_type: receiver_type,
|
2487
|
+
error: Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2488
|
+
)
|
2489
|
+
)
|
2431
2490
|
|
2432
|
-
|
2433
|
-
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2491
|
+
when AST::Types::Self
|
2492
|
+
expanded_self = expand_self(receiver_type)
|
2493
|
+
|
2494
|
+
if expanded_self.is_a?(AST::Types::Self)
|
2495
|
+
Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
|
2496
|
+
|
2497
|
+
constr = constr.synthesize_children(node, skips: [receiver])
|
2498
|
+
constr.add_call(
|
2499
|
+
TypeInference::MethodCall::NoMethodError.new(
|
2500
|
+
node: node,
|
2501
|
+
context: context.method_context,
|
2502
|
+
method_name: method_name,
|
2503
|
+
receiver_type: receiver_type,
|
2504
|
+
error: Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
2505
|
+
)
|
2506
|
+
)
|
2507
|
+
else
|
2508
|
+
interface = checker.factory.interface(expanded_self,
|
2509
|
+
private: !receiver,
|
2510
|
+
self_type: AST::Types::Self.new)
|
2511
|
+
|
2512
|
+
constr.type_send_interface(node,
|
2513
|
+
interface: interface,
|
2514
|
+
receiver: receiver,
|
2515
|
+
receiver_type: expanded_self,
|
2516
|
+
method_name: method_name,
|
2517
|
+
arguments: arguments,
|
2518
|
+
block_params: block_params,
|
2519
|
+
block_body: block_body)
|
2520
|
+
end
|
2521
|
+
else
|
2522
|
+
interface = checker.factory.interface(receiver_type,
|
2523
|
+
private: !receiver,
|
2524
|
+
self_type: receiver_type)
|
2525
|
+
|
2526
|
+
constr.type_send_interface(node,
|
2527
|
+
interface: interface,
|
2528
|
+
receiver: receiver,
|
2529
|
+
receiver_type: receiver_type,
|
2530
|
+
method_name: method_name,
|
2531
|
+
arguments: arguments,
|
2532
|
+
block_params: block_params,
|
2533
|
+
block_body: block_body)
|
2534
|
+
end
|
2535
|
+
|
2536
|
+
Pair.new(type: type, constr: constr)
|
2537
|
+
rescue => exn
|
2538
|
+
case exn
|
2539
|
+
when RBS::NoTypeFoundError, RBS::NoMixinFoundError, RBS::NoSuperclassFoundError, RBS::InvalidTypeApplicationError
|
2540
|
+
# ignore known RBS errors.
|
2541
|
+
else
|
2542
|
+
Steep.log_error(exn, message: "Unexpected error in #type_send: #{exn.message} (#{exn.class})")
|
2543
|
+
end
|
2544
|
+
|
2545
|
+
error = Errors::UnexpectedError.new(node: node, error: exn)
|
2546
|
+
|
2547
|
+
type_any_rec(node)
|
2548
|
+
|
2549
|
+
add_call(
|
2550
|
+
TypeInference::MethodCall::Error.new(
|
2551
|
+
node: node,
|
2552
|
+
context: context.method_context,
|
2553
|
+
method_name: method_name,
|
2554
|
+
receiver_type: receiver_type,
|
2555
|
+
errors: [error]
|
2445
2556
|
)
|
2446
|
-
)
|
2557
|
+
)
|
2447
2558
|
end
|
2448
2559
|
|
2449
2560
|
def expand_self(type)
|
@@ -2463,63 +2574,54 @@ module Steep
|
|
2463
2574
|
|
2464
2575
|
zips.map do |arg_pairs|
|
2465
2576
|
typing.new_child(node_range) do |child_typing|
|
2466
|
-
|
2577
|
+
self.with_new_typing(child_typing).try_method_type(
|
2467
2578
|
node,
|
2468
2579
|
receiver_type: receiver_type,
|
2580
|
+
method_name: method_name,
|
2469
2581
|
method_type: method_type,
|
2470
2582
|
args: args,
|
2471
2583
|
arg_pairs: arg_pairs,
|
2472
2584
|
block_params: block_params,
|
2473
2585
|
block_body: block_body,
|
2474
|
-
child_typing: child_typing,
|
2475
2586
|
topdown_hint: topdown_hint
|
2476
2587
|
)
|
2477
|
-
|
2478
|
-
raise unless ret.is_a?(Array) && ret[1].is_a?(TypeConstruction)
|
2479
|
-
|
2480
|
-
result, constr = ret
|
2481
|
-
|
2482
|
-
[result, constr, method_type]
|
2483
2588
|
end
|
2484
2589
|
end
|
2485
2590
|
end
|
2486
2591
|
end
|
2487
2592
|
|
2488
|
-
|
2489
|
-
|
2490
|
-
else
|
2593
|
+
case
|
2594
|
+
when results.empty?
|
2491
2595
|
method_type = method.method_types.last
|
2596
|
+
all_decls = method.method_types.each.with_object(Set[]) do |method_type, set|
|
2597
|
+
set.merge(method_type.method_decls)
|
2598
|
+
end
|
2599
|
+
error = Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
|
2600
|
+
call = TypeInference::MethodCall::Error.new(
|
2601
|
+
node: node,
|
2602
|
+
context: context.method_context,
|
2603
|
+
method_name: method_name,
|
2604
|
+
receiver_type: receiver_type,
|
2605
|
+
return_type: method_type.return_type,
|
2606
|
+
errors: [error],
|
2607
|
+
method_decls: all_decls
|
2608
|
+
)
|
2492
2609
|
constr = self.with_new_typing(typing.new_child(node_range))
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2498
|
-
when Errors::Base
|
2499
|
-
if method.method_types.size == 1
|
2500
|
-
typing.add_error result
|
2501
|
-
type = case method_type.return_type
|
2502
|
-
when AST::Types::Var
|
2503
|
-
AST::Builtin.any_type
|
2504
|
-
else
|
2505
|
-
method_type.return_type
|
2506
|
-
end
|
2610
|
+
when (call, constr = results.find {|call, _| call.is_a?(TypeInference::MethodCall::Typed) })
|
2611
|
+
# Nop
|
2612
|
+
else
|
2613
|
+
if results.one?
|
2614
|
+
call, constr = results[0]
|
2507
2615
|
else
|
2508
|
-
|
2509
|
-
receiver_type: expand_self(receiver_type),
|
2510
|
-
method_name: method_name,
|
2511
|
-
method_types: method.method_types)
|
2512
|
-
type = AST::Builtin.any_type
|
2616
|
+
return
|
2513
2617
|
end
|
2514
|
-
|
2515
|
-
[type,
|
2516
|
-
update_lvar_env { constr.context.lvar_env },
|
2517
|
-
result]
|
2518
|
-
else # Type
|
2519
|
-
[result,
|
2520
|
-
update_lvar_env { constr.context.lvar_env },
|
2521
|
-
nil]
|
2522
2618
|
end
|
2619
|
+
constr.typing.save!
|
2620
|
+
|
2621
|
+
[
|
2622
|
+
call,
|
2623
|
+
update_lvar_env { constr.context.lvar_env }
|
2624
|
+
]
|
2523
2625
|
end
|
2524
2626
|
|
2525
2627
|
def check_keyword_arg(receiver_type:, node:, method_type:, constraints:)
|
@@ -2621,14 +2723,12 @@ module Steep
|
|
2621
2723
|
|
2622
2724
|
hash_type = AST::Builtin::Hash.instance_type(
|
2623
2725
|
AST::Builtin::Symbol.instance_type,
|
2624
|
-
AST::Types::Union.build(types: value_types
|
2625
|
-
location: method_type.location)
|
2726
|
+
AST::Types::Union.build(types: value_types)
|
2626
2727
|
)
|
2627
2728
|
else
|
2628
2729
|
hash_elements = params.required_keywords.merge(
|
2629
2730
|
method_type.params.optional_keywords.transform_values do |type|
|
2630
|
-
AST::Types::Union.build(types: [type, AST::Builtin.nil_type]
|
2631
|
-
location: method_type.location)
|
2731
|
+
AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
|
2632
2732
|
end
|
2633
2733
|
)
|
2634
2734
|
|
@@ -2650,151 +2750,211 @@ module Steep
|
|
2650
2750
|
nil
|
2651
2751
|
end
|
2652
2752
|
|
2653
|
-
def try_method_type(node, receiver_type:, method_type:, args:, arg_pairs:, block_params:, block_body:,
|
2753
|
+
def try_method_type(node, receiver_type:, method_name:, method_type:, args:, arg_pairs:, block_params:, block_body:, topdown_hint:)
|
2654
2754
|
fresh_types = method_type.type_params.map {|x| AST::Types::Var.fresh(x)}
|
2655
2755
|
fresh_vars = Set.new(fresh_types.map(&:name))
|
2656
2756
|
instantiation = Interface::Substitution.build(method_type.type_params, fresh_types)
|
2657
2757
|
|
2658
|
-
|
2659
|
-
checker: checker,
|
2660
|
-
source: source,
|
2661
|
-
annotations: annotations,
|
2662
|
-
typing: child_typing,
|
2663
|
-
context: context
|
2664
|
-
)
|
2758
|
+
constr = self
|
2665
2759
|
|
2666
|
-
|
2760
|
+
method_type = method_type.instantiate(instantiation)
|
2667
2761
|
|
2668
|
-
|
2669
|
-
|
2670
|
-
|
2671
|
-
occurence = Subtyping::VariableOccurence.from_method_type(method_type)
|
2762
|
+
constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
|
2763
|
+
variance = Subtyping::VariableVariance.from_method_type(method_type)
|
2764
|
+
occurence = Subtyping::VariableOccurence.from_method_type(method_type)
|
2672
2765
|
|
2673
|
-
|
2674
|
-
case pair
|
2675
|
-
when Array
|
2676
|
-
(arg_node, param_type) = pair
|
2677
|
-
param_type = param_type.subst(instantiation)
|
2766
|
+
errors = []
|
2678
2767
|
|
2679
|
-
|
2680
|
-
|
2681
|
-
|
2682
|
-
|
2683
|
-
|
2768
|
+
arg_pairs.each do |pair|
|
2769
|
+
case pair
|
2770
|
+
when Array
|
2771
|
+
arg_node, param_type = pair
|
2772
|
+
param_type = param_type.subst(instantiation)
|
2684
2773
|
|
2685
|
-
|
2686
|
-
|
2774
|
+
arg_type, constr = if arg_node.type == :splat
|
2775
|
+
constr.synthesize(arg_node.children[0])
|
2776
|
+
else
|
2777
|
+
constr.synthesize(arg_node, hint: topdown_hint ? param_type : nil)
|
2778
|
+
end
|
2779
|
+
|
2780
|
+
check_relation(sub_type: arg_type, super_type: param_type, constraints: constraints).else do
|
2781
|
+
errors << Errors::ArgumentTypeMismatch.new(node: arg_node,
|
2687
2782
|
receiver_type: receiver_type,
|
2688
2783
|
expected: param_type,
|
2689
|
-
actual: arg_type)
|
2690
|
-
|
2691
|
-
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
constraints: constraints)
|
2784
|
+
actual: arg_type)
|
2785
|
+
end
|
2786
|
+
else
|
2787
|
+
# keyword
|
2788
|
+
result = constr.check_keyword_arg(receiver_type: receiver_type,
|
2789
|
+
node: pair,
|
2790
|
+
method_type: method_type,
|
2791
|
+
constraints: constraints)
|
2698
2792
|
|
2699
|
-
|
2700
|
-
|
2701
|
-
end
|
2793
|
+
if result.is_a?(Errors::Base)
|
2794
|
+
errors << result
|
2702
2795
|
end
|
2703
2796
|
end
|
2797
|
+
end
|
2704
2798
|
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
constr
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2799
|
+
if block_params
|
2800
|
+
# block is given
|
2801
|
+
block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
2802
|
+
block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
2803
|
+
|
2804
|
+
if method_type.block
|
2805
|
+
pairs = method_type.block && block_params_&.zip(method_type.block.type.params)
|
2806
|
+
|
2807
|
+
if pairs
|
2808
|
+
begin
|
2809
|
+
block_constr = constr.for_block(
|
2810
|
+
block_params: block_params_,
|
2811
|
+
block_param_hint: method_type.block.type.params,
|
2812
|
+
block_annotations: block_annotations,
|
2813
|
+
node_type_hint: method_type.return_type
|
2814
|
+
)
|
2815
|
+
block_constr = block_constr.with_new_typing(
|
2816
|
+
block_constr.typing.new_child(
|
2817
|
+
range: block_constr.typing.block_range(node)
|
2818
|
+
)
|
2819
|
+
)
|
2820
|
+
|
2821
|
+
block_constr.typing.add_context_for_body(node, context: block_constr.context)
|
2822
|
+
|
2823
|
+
pairs.each do |param, type|
|
2824
|
+
_, block_constr = block_constr.synthesize(param.node, hint: param.type || type)
|
2825
|
+
|
2826
|
+
if param.type
|
2827
|
+
check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
|
2828
|
+
error = Errors::IncompatibleAssignment.new(
|
2829
|
+
node: param.node,
|
2830
|
+
lhs_type: param.type,
|
2831
|
+
rhs_type: type,
|
2832
|
+
result: result
|
2833
|
+
)
|
2834
|
+
errors << error
|
2835
|
+
end
|
2836
|
+
end
|
2740
2837
|
end
|
2741
|
-
end
|
2742
|
-
end
|
2743
|
-
end
|
2744
2838
|
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2839
|
+
s = constraints.solution(
|
2840
|
+
checker,
|
2841
|
+
self_type: self_type,
|
2842
|
+
variance: variance,
|
2843
|
+
variables: method_type.params.free_variables + method_type.block.type.params.free_variables
|
2844
|
+
)
|
2845
|
+
method_type = method_type.subst(s)
|
2846
|
+
block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
|
2847
|
+
if block_body
|
2848
|
+
block_body_type = block_constr.synthesize_block(
|
2849
|
+
node: node,
|
2850
|
+
block_type_hint: method_type.block.type.return_type,
|
2851
|
+
block_body: block_body,
|
2852
|
+
topdown_hint: topdown_hint
|
2853
|
+
) do |error|
|
2854
|
+
errors << error
|
2855
|
+
end
|
2856
|
+
else
|
2857
|
+
block_body_type = AST::Builtin.nil_type
|
2858
|
+
end
|
2859
|
+
|
2860
|
+
result = check_relation(sub_type: block_body_type,
|
2762
2861
|
super_type: method_type.block.type.return_type,
|
2763
2862
|
constraints: constraints)
|
2764
2863
|
|
2765
2864
|
case result
|
2766
2865
|
when Subtyping::Result::Success
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
[ty, constr]
|
2866
|
+
s = constraints.solution(checker, self_type: self_type, variance: variance, variables: fresh_vars)
|
2867
|
+
method_type = method_type.subst(s)
|
2868
|
+
|
2869
|
+
return_type = method_type.return_type
|
2870
|
+
if break_type = block_annotations.break_type
|
2871
|
+
return_type = union_type(break_type, return_type)
|
2774
2872
|
end
|
2775
2873
|
|
2776
2874
|
when Subtyping::Result::Failure
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2875
|
+
block_type = AST::Types::Proc.new(
|
2876
|
+
params: method_type.block.type.params || block_params.params_type,
|
2877
|
+
return_type: block_body_type
|
2878
|
+
)
|
2879
|
+
errors << Errors::BlockTypeMismatch.new(node: node,
|
2880
|
+
expected: method_type.block.type,
|
2881
|
+
actual: block_type,
|
2882
|
+
result: result)
|
2883
|
+
|
2884
|
+
return_type = method_type.return_type
|
2782
2885
|
end
|
2886
|
+
|
2887
|
+
block_constr.typing.save!
|
2888
|
+
rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
|
2889
|
+
errors << Errors::UnsatisfiableConstraint.new(
|
2890
|
+
node: node,
|
2891
|
+
method_type: method_type,
|
2892
|
+
var: exn.var,
|
2893
|
+
sub_type: exn.sub_type,
|
2894
|
+
super_type: exn.super_type,
|
2895
|
+
result: exn.result
|
2896
|
+
)
|
2897
|
+
|
2898
|
+
constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
|
2899
|
+
errors << error
|
2900
|
+
end
|
2901
|
+
|
2902
|
+
s = Interface::Substitution.build(method_type.free_variables,
|
2903
|
+
Array.new(method_type.free_variables.size, AST::Builtin.any_type))
|
2904
|
+
method_type = method_type.subst(s)
|
2783
2905
|
end
|
2906
|
+
else
|
2907
|
+
errors << Errors::UnsupportedSyntax.new(
|
2908
|
+
node: block_params,
|
2909
|
+
message: "Unsupported block params pattern, probably masgn?"
|
2910
|
+
)
|
2911
|
+
|
2912
|
+
s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
|
2913
|
+
method_type = method_type.subst(s)
|
2914
|
+
end
|
2915
|
+
else
|
2916
|
+
# Block is given but method doesn't accept
|
2917
|
+
#
|
2918
|
+
constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
|
2919
|
+
errors << error
|
2920
|
+
end
|
2784
2921
|
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2922
|
+
errors << Errors::UnexpectedBlockGiven.new(
|
2923
|
+
node: node,
|
2924
|
+
method_type: method_type
|
2925
|
+
)
|
2926
|
+
end
|
2927
|
+
else
|
2928
|
+
# block is not given
|
2929
|
+
if (!method_type.block || method_type.block.optional?)
|
2930
|
+
# Method call without block is allowed
|
2931
|
+
unless args.block_pass_arg
|
2932
|
+
# OK, without block
|
2933
|
+
s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
|
2934
|
+
method_type = method_type.subst(s)
|
2935
|
+
else
|
2936
|
+
# &block arg is given
|
2937
|
+
s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
|
2938
|
+
method_type = method_type.subst(s)
|
2939
|
+
|
2940
|
+
errors << Errors::UnexpectedBlockGiven.new(
|
2941
|
+
node: node,
|
2942
|
+
method_type: method_type
|
2943
|
+
)
|
2793
2944
|
end
|
2945
|
+
else
|
2946
|
+
unless args.block_pass_arg
|
2947
|
+
# Required block is missing
|
2948
|
+
errors << Errors::RequiredBlockMissing.new(
|
2949
|
+
node: node,
|
2950
|
+
method_type: method_type
|
2951
|
+
)
|
2794
2952
|
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2953
|
+
s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
|
2954
|
+
method_type = method_type.subst(s)
|
2955
|
+
else
|
2956
|
+
begin
|
2957
|
+
method_type = method_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: occurence.params))
|
2798
2958
|
block_type, constr = constr.synthesize(args.block_pass_arg, hint: topdown_hint ? method_type.block.type : nil)
|
2799
2959
|
result = check_relation(
|
2800
2960
|
sub_type: block_type,
|
@@ -2808,68 +2968,65 @@ module Steep
|
|
2808
2968
|
constraints: constraints
|
2809
2969
|
)
|
2810
2970
|
|
2811
|
-
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
2815
|
-
|
2816
|
-
]
|
2817
|
-
|
2818
|
-
when Subtyping::Result::Failure
|
2819
|
-
[
|
2820
|
-
Errors::BlockTypeMismatch.new(node: node,
|
2821
|
-
expected: method_type.block.type,
|
2822
|
-
actual: block_type,
|
2823
|
-
result: result),
|
2824
|
-
constr
|
2825
|
-
]
|
2971
|
+
result.else do |result|
|
2972
|
+
errors << Errors::BlockTypeMismatch.new(node: node,
|
2973
|
+
expected: method_type.block.type,
|
2974
|
+
actual: block_type,
|
2975
|
+
result: result)
|
2826
2976
|
end
|
2977
|
+
|
2978
|
+
method_type = method_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: method_type.free_variables))
|
2827
2979
|
end
|
2980
|
+
end
|
2981
|
+
end
|
2982
|
+
end
|
2828
2983
|
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2832
|
-
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
|
2842
|
-
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2984
|
+
call = if errors.empty?
|
2985
|
+
TypeInference::MethodCall::Typed.new(
|
2986
|
+
node: node,
|
2987
|
+
context: context.method_context,
|
2988
|
+
receiver_type: receiver_type,
|
2989
|
+
method_name: method_name,
|
2990
|
+
actual_method_type: method_type,
|
2991
|
+
return_type: return_type || method_type.return_type,
|
2992
|
+
method_decls: method_type.method_decls
|
2993
|
+
)
|
2994
|
+
else
|
2995
|
+
TypeInference::MethodCall::Error.new(
|
2996
|
+
node: node,
|
2997
|
+
context: context.method_context,
|
2998
|
+
receiver_type: receiver_type,
|
2999
|
+
method_name: method_name,
|
3000
|
+
return_type: return_type || method_type.return_type,
|
3001
|
+
method_decls: method_type.method_decls,
|
3002
|
+
errors: errors
|
3003
|
+
)
|
3004
|
+
end
|
3005
|
+
|
3006
|
+
[
|
3007
|
+
call,
|
3008
|
+
constr
|
3009
|
+
]
|
3010
|
+
end
|
3011
|
+
|
3012
|
+
def type_block_without_hint(node:, block_annotations:, block_params:, block_body:, &block)
|
3013
|
+
block_constr = for_block(
|
3014
|
+
block_params: block_params,
|
3015
|
+
block_param_hint: nil,
|
3016
|
+
block_annotations: block_annotations,
|
3017
|
+
node_type_hint: nil
|
3018
|
+
)
|
2856
3019
|
|
2857
|
-
|
2858
|
-
[
|
2859
|
-
Errors::RequiredBlockMissing.new(
|
2860
|
-
node: node,
|
2861
|
-
method_type: method_type
|
2862
|
-
),
|
2863
|
-
constr
|
2864
|
-
]
|
3020
|
+
block_constr.typing.add_context_for_body(node, context: block_constr.context)
|
2865
3021
|
|
2866
|
-
|
2867
|
-
|
2868
|
-
end
|
3022
|
+
block_params.params.each do |param|
|
3023
|
+
_, block_constr = block_constr.synthesize(param.node, hint: param.type)
|
2869
3024
|
end
|
3025
|
+
|
3026
|
+
block_constr.synthesize_block(node: node, block_type_hint: nil, block_body: block_body, topdown_hint: false, &block)
|
2870
3027
|
end
|
2871
3028
|
|
2872
|
-
def
|
3029
|
+
def for_block(block_params:, block_param_hint:, block_annotations:, node_type_hint:)
|
2873
3030
|
block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
|
2874
3031
|
|
2875
3032
|
param_types_hash = {}
|
@@ -2885,30 +3042,30 @@ module Steep
|
|
2885
3042
|
end
|
2886
3043
|
end
|
2887
3044
|
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
3045
|
+
decls = param_types_hash.each.with_object({}) do |(name, type), hash|
|
3046
|
+
hash[name] = TypeInference::LocalVariableTypeEnv::Entry.new(type: type)
|
3047
|
+
end
|
3048
|
+
lvar_env = context.lvar_env
|
3049
|
+
.pin_assignments
|
3050
|
+
.except(decls.keys)
|
3051
|
+
.update(assigned_types: decls)
|
3052
|
+
.annotate(block_annotations)
|
2894
3053
|
|
2895
3054
|
break_type = if block_annotations.break_type
|
2896
3055
|
union_type(node_type_hint, block_annotations.break_type)
|
2897
3056
|
else
|
2898
3057
|
node_type_hint
|
2899
3058
|
end
|
2900
|
-
Steep.logger.debug("return_type = #{break_type}")
|
2901
|
-
|
2902
|
-
block_context = TypeInference::Context::BlockContext.new(body_type: block_annotations.block_type)
|
2903
|
-
Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
|
2904
3059
|
|
3060
|
+
block_context = TypeInference::Context::BlockContext.new(
|
3061
|
+
body_type: block_annotations.block_type
|
3062
|
+
)
|
2905
3063
|
break_context = TypeInference::Context::BreakContext.new(
|
2906
3064
|
break_type: break_type,
|
2907
3065
|
next_type: block_context.body_type
|
2908
3066
|
)
|
2909
|
-
Steep.logger.debug("break_context { type: #{break_context.break_type} }")
|
2910
3067
|
|
2911
|
-
|
3068
|
+
self.class.new(
|
2912
3069
|
checker: checker,
|
2913
3070
|
source: source,
|
2914
3071
|
annotations: annotations.merge_block_annotations(block_annotations),
|
@@ -2920,37 +3077,34 @@ module Steep
|
|
2920
3077
|
break_context: break_context,
|
2921
3078
|
self_type: block_annotations.self_type || self_type,
|
2922
3079
|
type_env: type_env.dup,
|
2923
|
-
lvar_env: lvar_env
|
3080
|
+
lvar_env: lvar_env,
|
3081
|
+
call_context: self.context.call_context
|
2924
3082
|
)
|
2925
3083
|
)
|
3084
|
+
end
|
2926
3085
|
|
2927
|
-
|
2928
|
-
|
3086
|
+
def synthesize_block(node:, block_type_hint:, block_body:, topdown_hint:)
|
2929
3087
|
if block_body
|
2930
|
-
|
2931
|
-
|
2932
|
-
|
2933
|
-
|
2934
|
-
|
2935
|
-
|
2936
|
-
|
2937
|
-
|
2938
|
-
|
2939
|
-
|
2940
|
-
|
3088
|
+
body_type, _, context =
|
3089
|
+
if (body_type = block_context.body_type)
|
3090
|
+
check(block_body, body_type) do |expected, actual, result|
|
3091
|
+
error = Errors::BlockTypeMismatch.new(node: block_body,
|
3092
|
+
expected: expected,
|
3093
|
+
actual: actual,
|
3094
|
+
result: result)
|
3095
|
+
yield(error) if block_given?
|
3096
|
+
end
|
3097
|
+
else
|
3098
|
+
synthesize(block_body, hint: topdown_hint ? block_type_hint : nil)
|
3099
|
+
end
|
2941
3100
|
|
2942
3101
|
range = block_body.loc.expression.end_pos..node.loc.end.begin_pos
|
2943
|
-
typing.add_context(range, context:
|
3102
|
+
typing.add_context(range, context: context)
|
3103
|
+
|
3104
|
+
body_type
|
2944
3105
|
else
|
2945
|
-
|
3106
|
+
AST::Builtin.nil_type
|
2946
3107
|
end
|
2947
|
-
|
2948
|
-
body_pair.with(
|
2949
|
-
type: AST::Types::Proc.new(
|
2950
|
-
params: block_param_hint || block_params.params_type,
|
2951
|
-
return_type: body_pair.type
|
2952
|
-
)
|
2953
|
-
)
|
2954
3108
|
end
|
2955
3109
|
|
2956
3110
|
def each_child_node(node)
|
@@ -3172,6 +3326,14 @@ module Steep
|
|
3172
3326
|
!nodes.empty? && nodes.all? {|child| child.type == :class || child.type == :module}
|
3173
3327
|
end
|
3174
3328
|
|
3329
|
+
def type_any_rec(node)
|
3330
|
+
add_typing node, type: AST::Builtin.any_type
|
3331
|
+
|
3332
|
+
each_child_node(node) do |child|
|
3333
|
+
type_any_rec(child)
|
3334
|
+
end
|
3335
|
+
end
|
3336
|
+
|
3175
3337
|
def fallback_any_rec(node)
|
3176
3338
|
fallback_to_any(node) unless typing.has_type?(node)
|
3177
3339
|
|