typeprof 0.5.4 → 0.6.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/Gemfile.lock +1 -1
- data/lib/typeprof/analyzer.rb +123 -65
- data/lib/typeprof/builtin.rb +19 -8
- data/lib/typeprof/container-type.rb +9 -9
- data/lib/typeprof/export.rb +5 -5
- data/lib/typeprof/import.rb +24 -14
- data/lib/typeprof/method.rb +32 -15
- data/lib/typeprof/type.rb +15 -13
- data/lib/typeprof/version.rb +1 -1
- data/smoke/parameterizedd-self2.rb +15 -0
- data/smoke/rbs-tyvar6.rb +17 -0
- data/smoke/rbs-tyvar6.rbs +12 -0
- data/smoke/super4.rb +43 -0
- data/smoke/super5.rb +36 -0
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '080db9120b2b069f8a1385e3696851212a2271652f73b8627d5337d2d26d8f2b'
|
4
|
+
data.tar.gz: 969e38b2a1b64ec3fbe90551b440418901c8af028c7126b1f56acaca3818d2b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 322bff1d2a49e9a2729012064e393138cb9e4b81472e1c75b14a2d55a4fe3616ef3efc5ecf5df3a156a418ff6ad0281c24c2c585c61a733db0c6e4d05ceb6595
|
7
|
+
data.tar.gz: 78de3b56104b239c272938a9877bfdd49ccf20df8dbd360bf5fe7ef3c342e1d746c2adbf957fd511c03156258effe630c440941e600d58b7e7cd914ff11ca4d5
|
data/Gemfile.lock
CHANGED
data/lib/typeprof/analyzer.rb
CHANGED
@@ -281,11 +281,10 @@ module TypeProf
|
|
281
281
|
attr_reader :class_defs
|
282
282
|
|
283
283
|
class ClassDef # or ModuleDef
|
284
|
-
def initialize(kind, name,
|
284
|
+
def initialize(kind, name, absolute_path)
|
285
285
|
raise unless name.is_a?(Array)
|
286
286
|
@kind = kind
|
287
|
-
@
|
288
|
-
@modules = { true => {}, false => {} }
|
287
|
+
@modules = { true => [], false => [] }
|
289
288
|
@name = name
|
290
289
|
@consts = {}
|
291
290
|
@methods = {}
|
@@ -295,14 +294,16 @@ module TypeProf
|
|
295
294
|
@namespace = nil
|
296
295
|
end
|
297
296
|
|
298
|
-
attr_reader :kind, :
|
297
|
+
attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
|
299
298
|
attr_accessor :name, :klass_obj
|
300
299
|
|
301
|
-
def include_module(mod, singleton, absolute_path)
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
300
|
+
def include_module(mod, type_args, singleton, absolute_path)
|
301
|
+
module_type_args, _, absolute_paths = @modules[singleton].find {|m,| m == mod }
|
302
|
+
if module_type_args
|
303
|
+
raise "inconsistent include/extend type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil
|
304
|
+
else
|
305
|
+
absolute_paths = Utils::MutableSet.new
|
306
|
+
@modules[singleton].unshift([mod, type_args, absolute_paths])
|
306
307
|
end
|
307
308
|
absolute_paths << absolute_path
|
308
309
|
end
|
@@ -319,13 +320,26 @@ module TypeProf
|
|
319
320
|
@consts[name] = [ty, absolute_path]
|
320
321
|
end
|
321
322
|
|
322
|
-
def
|
323
|
-
@methods[[singleton, mid]]
|
324
|
-
|
325
|
-
|
326
|
-
|
323
|
+
def generate_substitution(singleton, mid, mthd, subst, &blk)
|
324
|
+
mthds = @methods[[singleton, mid]]
|
325
|
+
yield subst if mthds&.include?(mthd)
|
326
|
+
@modules[singleton].each do |mod_def, type_args,|
|
327
|
+
if mod_def.klass_obj.type_params && type_args
|
328
|
+
subst2 = {}
|
329
|
+
mod_def.klass_obj.type_params.zip(type_args) do |(tyvar, *), tyarg|
|
330
|
+
tyvar = Type::Var.new(tyvar)
|
331
|
+
subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
|
332
|
+
end
|
333
|
+
mod_def.generate_substitution(false, mid, mthd, subst2, &blk)
|
327
334
|
end
|
328
|
-
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def search_method(singleton, mid, &blk)
|
339
|
+
mthds = @methods[[singleton, mid]]
|
340
|
+
yield mthds, @klass_obj, singleton if mthds
|
341
|
+
@modules[singleton].each do |mod_def,|
|
342
|
+
mod_def.search_method(false, mid, &blk)
|
329
343
|
end
|
330
344
|
end
|
331
345
|
|
@@ -349,7 +363,7 @@ module TypeProf
|
|
349
363
|
end
|
350
364
|
end
|
351
365
|
|
352
|
-
def include_module(including_mod, included_mod, singleton, absolute_path)
|
366
|
+
def include_module(including_mod, included_mod, type_args, singleton, absolute_path)
|
353
367
|
return if included_mod == Type.any
|
354
368
|
|
355
369
|
including_mod = @class_defs[including_mod.idx]
|
@@ -357,7 +371,7 @@ module TypeProf
|
|
357
371
|
if included_mod.is_a?(Type::Class)
|
358
372
|
included_mod = @class_defs[included_mod.idx]
|
359
373
|
if included_mod && included_mod.kind == :module
|
360
|
-
including_mod.include_module(included_mod, singleton, absolute_path)
|
374
|
+
including_mod.include_module(included_mod, type_args, singleton, absolute_path)
|
361
375
|
else
|
362
376
|
warn "including something that is not a module"
|
363
377
|
end
|
@@ -369,25 +383,20 @@ module TypeProf
|
|
369
383
|
cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
|
370
384
|
end
|
371
385
|
|
372
|
-
def new_class(cbase, name, type_params, superclass, absolute_path)
|
386
|
+
def new_class(cbase, name, type_params, superclass, superclass_type_args, absolute_path)
|
373
387
|
show_name = cbase_path(cbase) + [name]
|
374
388
|
idx = @class_defs.size
|
375
389
|
if superclass
|
376
|
-
|
377
|
-
|
378
|
-
else
|
379
|
-
superclass_idx = superclass.idx
|
380
|
-
end
|
381
|
-
@class_defs[idx] = ClassDef.new(:class, show_name, superclass_idx, absolute_path)
|
382
|
-
klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
|
390
|
+
@class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
|
391
|
+
klass = Type::Class.new(:class, idx, type_params, superclass, superclass_type_args, show_name)
|
383
392
|
@class_defs[idx].klass_obj = klass
|
384
393
|
cbase ||= klass # for bootstrap
|
385
394
|
add_constant(cbase, name, klass, absolute_path)
|
386
395
|
return klass
|
387
396
|
else
|
388
397
|
# module
|
389
|
-
@class_defs[idx] = ClassDef.new(:module, show_name,
|
390
|
-
mod = Type::Class.new(:module, idx, type_params, nil, show_name)
|
398
|
+
@class_defs[idx] = ClassDef.new(:module, show_name, absolute_path)
|
399
|
+
mod = Type::Class.new(:module, idx, type_params, nil, nil, show_name)
|
391
400
|
@class_defs[idx].klass_obj = mod
|
392
401
|
add_constant(cbase, name, mod, absolute_path)
|
393
402
|
return mod
|
@@ -400,8 +409,8 @@ module TypeProf
|
|
400
409
|
idx = @class_defs.size
|
401
410
|
superclass = Type::Builtin[:struct]
|
402
411
|
name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
|
403
|
-
@class_defs[idx] = ClassDef.new(:class, [name],
|
404
|
-
klass = Type::Class.new(:class, idx, [], superclass, name)
|
412
|
+
@class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
|
413
|
+
klass = Type::Class.new(:class, idx, [], superclass, [], name)
|
405
414
|
@class_defs[idx].klass_obj = klass
|
406
415
|
|
407
416
|
@struct_defs[ep] = klass
|
@@ -431,28 +440,75 @@ module TypeProf
|
|
431
440
|
end
|
432
441
|
end
|
433
442
|
|
443
|
+
def generate_substitution(klass, singleton, mid, mthd, subst, &blk)
|
444
|
+
if klass.kind == :class
|
445
|
+
while klass != :__root__
|
446
|
+
class_def = @class_defs[klass.idx]
|
447
|
+
class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
|
448
|
+
if klass.superclass && klass.superclass_type_args
|
449
|
+
subst2 = {}
|
450
|
+
klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
|
451
|
+
tyvar = Type::Var.new(tyvar)
|
452
|
+
subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
|
453
|
+
end
|
454
|
+
subst = subst2
|
455
|
+
end
|
456
|
+
klass = klass.superclass
|
457
|
+
end
|
458
|
+
else
|
459
|
+
# module
|
460
|
+
class_def = @class_defs[klass.idx]
|
461
|
+
class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
def search_method(klass, singleton, mid, &blk)
|
466
|
+
# XXX: support method alias correctly
|
467
|
+
klass_orig = klass
|
468
|
+
if klass.kind == :class
|
469
|
+
while klass != :__root__
|
470
|
+
class_def = @class_defs[klass.idx]
|
471
|
+
class_def.search_method(singleton, mid, &blk)
|
472
|
+
klass = klass.superclass
|
473
|
+
end
|
474
|
+
else
|
475
|
+
# module
|
476
|
+
class_def = @class_defs[klass.idx]
|
477
|
+
class_def.search_method(singleton, mid, &blk)
|
478
|
+
end
|
479
|
+
if singleton
|
480
|
+
search_method(Type::Builtin[klass_orig.kind], false, mid, &blk)
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
434
484
|
def get_method(klass, singleton, mid)
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
485
|
+
search_method(klass, singleton, mid) {|mthds,| return mthds }
|
486
|
+
end
|
487
|
+
|
488
|
+
def get_all_super_methods(klass, singleton, current_klass, mid)
|
489
|
+
hit = false
|
490
|
+
search_method(klass, singleton, mid) do |mthds, klass0, singleton0|
|
491
|
+
yield mthds, klass0, singleton0 if hit
|
492
|
+
hit = klass0 == current_klass
|
442
493
|
end
|
443
|
-
return get_method(Type::Builtin[:class], false, mid) if singleton
|
444
|
-
nil
|
445
494
|
end
|
446
495
|
|
447
496
|
def get_super_method(ctx, singleton)
|
448
|
-
|
497
|
+
klass = ctx.cref.klass
|
449
498
|
mid = ctx.mid
|
450
|
-
|
451
|
-
|
452
|
-
|
499
|
+
if klass.kind == :class
|
500
|
+
klass = klass.superclass
|
501
|
+
while klass != :__root__
|
502
|
+
class_def = @class_defs[klass.idx]
|
503
|
+
mthd = class_def.get_method(mid, singleton)
|
504
|
+
return mthd if mthd
|
505
|
+
klass = klass.superclass
|
506
|
+
end
|
507
|
+
else
|
508
|
+
# module
|
509
|
+
class_def = @class_defs[klass.idx]
|
453
510
|
mthd = class_def.get_method(mid, singleton)
|
454
511
|
return mthd if mthd
|
455
|
-
idx = class_def.superclass
|
456
512
|
end
|
457
513
|
nil
|
458
514
|
end
|
@@ -1157,7 +1213,8 @@ module TypeProf
|
|
1157
1213
|
if cbase == Type.any
|
1158
1214
|
klass = Type.any
|
1159
1215
|
else
|
1160
|
-
|
1216
|
+
superclass_type_args = superclass.type_params.map { Type.any } if superclass
|
1217
|
+
klass = new_class(cbase, id, [], superclass, superclass_type_args, ep.ctx.iseq.absolute_path)
|
1161
1218
|
end
|
1162
1219
|
end
|
1163
1220
|
singleton = false
|
@@ -1245,30 +1302,30 @@ module TypeProf
|
|
1245
1302
|
end
|
1246
1303
|
when :invokesuper
|
1247
1304
|
env, recv, _, aargs = setup_actual_arguments(:method, operands, ep, env)
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1305
|
+
mid = ep.ctx.mid
|
1306
|
+
found = false
|
1307
|
+
recv.each_child_global do |recv|
|
1308
|
+
klass, singleton = recv.method_dispatch_info
|
1309
|
+
next unless klass
|
1310
|
+
get_all_super_methods(klass, singleton, ep.ctx.cref.klass, ep.ctx.mid) do |meths, klass|
|
1311
|
+
found = true
|
1312
|
+
meths.each do |meth|
|
1313
|
+
# XXX: this decomposition is really needed??
|
1314
|
+
# It calls `Object.new` with union receiver which causes an error, but
|
1315
|
+
# it may be a fault of builtin Object.new implementation.
|
1316
|
+
recv.each_child do |recv|
|
1317
|
+
meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
|
1318
|
+
nenv, ret_ty, = localize_type(ret_ty, env, ep)
|
1319
|
+
nenv = nenv.push(ret_ty)
|
1320
|
+
merge_env(ep.next, nenv)
|
1321
|
+
end
|
1264
1322
|
end
|
1265
1323
|
end
|
1266
1324
|
end
|
1267
|
-
return
|
1268
|
-
else
|
1269
|
-
error(ep, "no superclass method: #{ env.static_env.recv_ty.screen_name(self) }##{ mid }")
|
1270
|
-
env = env.push(Type.any)
|
1271
1325
|
end
|
1326
|
+
return if found
|
1327
|
+
error(ep, "no superclass method: #{ env.static_env.recv_ty.screen_name(self) }##{ mid }")
|
1328
|
+
env = env.push(Type.any)
|
1272
1329
|
when :invokebuiltin
|
1273
1330
|
raise NotImplementedError
|
1274
1331
|
when :leave
|
@@ -1916,7 +1973,8 @@ module TypeProf
|
|
1916
1973
|
end
|
1917
1974
|
|
1918
1975
|
def do_send(recv, mid, aargs, ep, env, &ctn)
|
1919
|
-
|
1976
|
+
klass, singleton = recv.method_dispatch_info
|
1977
|
+
meths = get_method(klass, singleton, mid) if klass
|
1920
1978
|
if meths
|
1921
1979
|
meths.each do |meth|
|
1922
1980
|
meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
|
data/lib/typeprof/builtin.rb
CHANGED
@@ -100,7 +100,8 @@ module TypeProf
|
|
100
100
|
raise unless aargs.lead_tys.size != 0
|
101
101
|
sym = get_sym("respond_to?", aargs.lead_tys[0], ep, scratch)
|
102
102
|
if sym
|
103
|
-
|
103
|
+
klass, singleton = recv.method_dispatch_info
|
104
|
+
if scratch.get_method(klass, singleton, sym)
|
104
105
|
true_val = Type::Instance.new(Type::Builtin[:true])
|
105
106
|
ctn[true_val, ep, env]
|
106
107
|
else
|
@@ -143,7 +144,7 @@ module TypeProf
|
|
143
144
|
def object_instance_eval(recv, mid, aargs, ep, env, scratch, &ctn)
|
144
145
|
if aargs.lead_tys.size >= 1
|
145
146
|
scratch.warn(ep, "instance_eval with arguments are ignored")
|
146
|
-
ctn[
|
147
|
+
ctn[Type.any, ep, env]
|
147
148
|
return
|
148
149
|
end
|
149
150
|
naargs = ActualArguments.new([recv], nil, {}, Type.nil)
|
@@ -153,20 +154,30 @@ module TypeProf
|
|
153
154
|
end
|
154
155
|
|
155
156
|
def module_include(recv, mid, aargs, ep, env, scratch, &ctn)
|
157
|
+
if aargs.lead_tys.size != 1
|
158
|
+
scratch.warn(ep, "Module#include without an argument are ignored")
|
159
|
+
ctn[Type.any, ep, env]
|
160
|
+
return
|
161
|
+
end
|
156
162
|
arg = aargs.lead_tys[0]
|
157
163
|
arg.each_child do |arg|
|
158
164
|
if arg.is_a?(Type::Class)
|
159
|
-
scratch.include_module(recv, arg, false, ep.ctx.iseq.absolute_path)
|
165
|
+
scratch.include_module(recv, arg, nil, false, ep.ctx.iseq.absolute_path)
|
160
166
|
end
|
161
167
|
end
|
162
168
|
ctn[recv, ep, env]
|
163
169
|
end
|
164
170
|
|
165
171
|
def module_extend(recv, mid, aargs, ep, env, scratch, &ctn)
|
172
|
+
if aargs.lead_tys.size != 1
|
173
|
+
scratch.warn(ep, "Module#extend without an argument are ignored")
|
174
|
+
ctn[Type.any, ep, env]
|
175
|
+
return
|
176
|
+
end
|
166
177
|
arg = aargs.lead_tys[0]
|
167
178
|
arg.each_child do |arg|
|
168
179
|
if arg.is_a?(Type::Class)
|
169
|
-
scratch.include_module(recv, arg, true, ep.ctx.iseq.absolute_path)
|
180
|
+
scratch.include_module(recv, arg, nil, true, ep.ctx.iseq.absolute_path)
|
170
181
|
end
|
171
182
|
end
|
172
183
|
ctn[recv, ep, env]
|
@@ -178,7 +189,7 @@ module TypeProf
|
|
178
189
|
else
|
179
190
|
aargs.lead_tys.each do |aarg|
|
180
191
|
sym = get_sym("module_function", aarg, ep, scratch) or next
|
181
|
-
meths =
|
192
|
+
meths = scratch.get_method(recv, false, sym)
|
182
193
|
meths.each do |mdef|
|
183
194
|
scratch.add_method(recv, sym, true, mdef)
|
184
195
|
end
|
@@ -491,8 +502,8 @@ module TypeProf
|
|
491
502
|
end
|
492
503
|
|
493
504
|
def self.setup_initial_global_env(scratch)
|
494
|
-
klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil) # cbase, name, superclass
|
495
|
-
klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, nil)
|
505
|
+
klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil, nil) # cbase, name, superclass
|
506
|
+
klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, [], nil)
|
496
507
|
scratch.add_constant(klass_obj, :Object, klass_obj, nil)
|
497
508
|
scratch.add_constant(klass_obj, :BasicObject, klass_basic_obj, nil)
|
498
509
|
|
@@ -501,7 +512,7 @@ module TypeProf
|
|
501
512
|
|
502
513
|
Import.import_builtin(scratch)
|
503
514
|
|
504
|
-
Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil)
|
515
|
+
Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj, [], nil)
|
505
516
|
Type::Builtin[:int] = scratch.get_constant(klass_obj, :Integer)
|
506
517
|
Type::Builtin[:float] = scratch.get_constant(klass_obj, :Float)
|
507
518
|
Type::Builtin[:rational] = scratch.get_constant(klass_obj, :Rational)
|
@@ -85,7 +85,7 @@ module TypeProf
|
|
85
85
|
Cell.new(@elems.limit_size(limit - 1), @base_type)
|
86
86
|
end
|
87
87
|
|
88
|
-
def
|
88
|
+
def method_dispatch_info
|
89
89
|
raise
|
90
90
|
end
|
91
91
|
|
@@ -214,8 +214,8 @@ module TypeProf
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
-
def
|
218
|
-
@base_type.
|
217
|
+
def method_dispatch_info
|
218
|
+
@base_type.method_dispatch_info
|
219
219
|
end
|
220
220
|
end
|
221
221
|
|
@@ -255,7 +255,7 @@ module TypeProf
|
|
255
255
|
Array.new(@elems.limit_size(limit - 1), @base_type)
|
256
256
|
end
|
257
257
|
|
258
|
-
def
|
258
|
+
def method_dispatch_info
|
259
259
|
raise
|
260
260
|
end
|
261
261
|
|
@@ -530,8 +530,8 @@ module TypeProf
|
|
530
530
|
end
|
531
531
|
end
|
532
532
|
|
533
|
-
def
|
534
|
-
@base_type.
|
533
|
+
def method_dispatch_info
|
534
|
+
@base_type.method_dispatch_info
|
535
535
|
end
|
536
536
|
end
|
537
537
|
|
@@ -565,7 +565,7 @@ module TypeProf
|
|
565
565
|
Hash.new(@elems.limit_size(limit - 1), @base_type)
|
566
566
|
end
|
567
567
|
|
568
|
-
def
|
568
|
+
def method_dispatch_info
|
569
569
|
raise
|
570
570
|
end
|
571
571
|
|
@@ -815,8 +815,8 @@ module TypeProf
|
|
815
815
|
end
|
816
816
|
end
|
817
817
|
|
818
|
-
def
|
819
|
-
@base_type.
|
818
|
+
def method_dispatch_info
|
819
|
+
@base_type.method_dispatch_info
|
820
820
|
end
|
821
821
|
end
|
822
822
|
end
|
data/lib/typeprof/export.rb
CHANGED
@@ -91,9 +91,9 @@ module TypeProf
|
|
91
91
|
def conv_class(namespace, class_def, inner_classes)
|
92
92
|
@scratch.namespace = namespace
|
93
93
|
|
94
|
-
if class_def.superclass
|
95
|
-
omit =
|
96
|
-
superclass = omit ? nil : @scratch.get_class_name(
|
94
|
+
if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
|
95
|
+
omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
|
96
|
+
superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
|
97
97
|
end
|
98
98
|
|
99
99
|
@scratch.namespace = class_def.name
|
@@ -105,12 +105,12 @@ module TypeProf
|
|
105
105
|
consts[name] = ty.screen_name(@scratch)
|
106
106
|
end
|
107
107
|
|
108
|
-
included_mods = class_def.modules[false].filter_map do |mod_def, absolute_paths|
|
108
|
+
included_mods = class_def.modules[false].filter_map do |mod_def, _type_args, absolute_paths|
|
109
109
|
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
110
110
|
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
111
111
|
end
|
112
112
|
|
113
|
-
extended_mods = class_def.modules[true].filter_map do |mod_def, absolute_paths|
|
113
|
+
extended_mods = class_def.modules[true].filter_map do |mod_def, _type_args, absolute_paths|
|
114
114
|
next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
|
115
115
|
Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
|
116
116
|
end
|
data/lib/typeprof/import.rb
CHANGED
@@ -100,9 +100,13 @@ module TypeProf
|
|
100
100
|
json = {}
|
101
101
|
|
102
102
|
each_class_decl do |name, decls|
|
103
|
-
super_class_name = get_super_class_name(name, decls)
|
104
103
|
klass = conv_type_name(name)
|
105
|
-
|
104
|
+
super_class_name, super_class_args = get_super_class(name, decls)
|
105
|
+
if super_class_name
|
106
|
+
name = conv_type_name(super_class_name)
|
107
|
+
type_args = super_class_args.map {|type| conv_type(type) }
|
108
|
+
superclass = [name, type_args]
|
109
|
+
end
|
106
110
|
|
107
111
|
type_params = nil
|
108
112
|
included_modules = []
|
@@ -165,7 +169,8 @@ module TypeProf
|
|
165
169
|
name = member.name
|
166
170
|
if name.kind == :class
|
167
171
|
mod = conv_type_name(name)
|
168
|
-
|
172
|
+
type_args = member.args.map {|type| conv_type(type) }
|
173
|
+
included_modules << [mod, type_args]
|
169
174
|
else
|
170
175
|
# including an interface is not supported yet
|
171
176
|
end
|
@@ -174,7 +179,8 @@ module TypeProf
|
|
174
179
|
name = member.name
|
175
180
|
if name.kind == :class
|
176
181
|
mod = conv_type_name(name)
|
177
|
-
|
182
|
+
type_args = member.args.map {|type| conv_type(type) }
|
183
|
+
extended_modules << [mod, type_args]
|
178
184
|
else
|
179
185
|
# extending a module with an interface is not supported yet
|
180
186
|
end
|
@@ -256,14 +262,15 @@ module TypeProf
|
|
256
262
|
end
|
257
263
|
end
|
258
264
|
|
259
|
-
def
|
265
|
+
def get_super_class(name, decls)
|
260
266
|
return nil if name == RBS::BuiltinNames::BasicObject.name
|
261
267
|
|
262
268
|
decls.each do |decl|
|
263
269
|
decl = decl.decl
|
264
270
|
case decl
|
265
271
|
when RBS::AST::Declarations::Class
|
266
|
-
|
272
|
+
super_class = decl.super_class
|
273
|
+
return super_class.name, super_class.args if super_class
|
267
274
|
when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface
|
268
275
|
return nil
|
269
276
|
else
|
@@ -271,7 +278,7 @@ module TypeProf
|
|
271
278
|
end
|
272
279
|
end
|
273
280
|
|
274
|
-
return RBS::BuiltinNames::Object.name
|
281
|
+
return RBS::BuiltinNames::Object.name, []
|
275
282
|
end
|
276
283
|
|
277
284
|
def conv_method_def(rbs_method_types)
|
@@ -467,8 +474,8 @@ module TypeProf
|
|
467
474
|
def import(explicit = false)
|
468
475
|
classes = @json[:classes].map do |classpath, cdef|
|
469
476
|
type_params = cdef[:type_params]
|
470
|
-
superclass
|
471
|
-
members
|
477
|
+
superclass, superclass_type_args = cdef[:superclass]
|
478
|
+
members = cdef[:members]
|
472
479
|
|
473
480
|
name = classpath.last
|
474
481
|
superclass = path_to_klass(superclass) if superclass
|
@@ -476,7 +483,8 @@ module TypeProf
|
|
476
483
|
|
477
484
|
klass = @scratch.get_constant(base_klass, name)
|
478
485
|
if klass.is_a?(Type::Any)
|
479
|
-
|
486
|
+
superclass_type_args = superclass_type_args&.map {|ty| conv_type(ty) }
|
487
|
+
klass = @scratch.new_class(base_klass, name, type_params, superclass, superclass_type_args, nil)
|
480
488
|
|
481
489
|
# There builtin classes are needed to interpret RBS declarations
|
482
490
|
case classpath
|
@@ -503,12 +511,14 @@ module TypeProf
|
|
503
511
|
cvars = members[:cvars]
|
504
512
|
rbs_sources = members[:rbs_sources]
|
505
513
|
|
506
|
-
included_modules.each do |mod|
|
507
|
-
|
514
|
+
included_modules.each do |mod, type_args|
|
515
|
+
type_args = type_args&.map {|ty| conv_type(ty) }
|
516
|
+
@scratch.include_module(klass, path_to_klass(mod), type_args, false, nil)
|
508
517
|
end
|
509
518
|
|
510
|
-
extended_modules.each do |mod|
|
511
|
-
|
519
|
+
extended_modules.each do |mod, type_args|
|
520
|
+
type_args = type_args&.map {|ty| conv_type(ty) }
|
521
|
+
@scratch.include_module(klass, path_to_klass(mod), type_args, true, nil)
|
512
522
|
end
|
513
523
|
|
514
524
|
methods.each do |(singleton, method_name), mdef|
|
data/lib/typeprof/method.rb
CHANGED
@@ -170,6 +170,34 @@ module TypeProf
|
|
170
170
|
|
171
171
|
def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
172
172
|
recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
|
173
|
+
|
174
|
+
tmp_subst = {}
|
175
|
+
case
|
176
|
+
when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
|
177
|
+
tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
|
178
|
+
tyvars.zip(recv.elems.elems) do |tyvar, elem|
|
179
|
+
if tmp_subst[tyvar]
|
180
|
+
tmp_subst[tyvar] = tmp_subst[tyvar].union(elem)
|
181
|
+
else
|
182
|
+
tmp_subst[tyvar] = elem
|
183
|
+
end
|
184
|
+
end
|
185
|
+
when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
|
186
|
+
tmp_subst = { Type::Var.new(:Elem) => recv.elems.squash }
|
187
|
+
when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
|
188
|
+
tyvar_k = Type::Var.new(:K)
|
189
|
+
tyvar_v = Type::Var.new(:V)
|
190
|
+
k_ty0, v_ty0 = recv.elems.squash
|
191
|
+
# XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type?
|
192
|
+
tmp_subst = { tyvar_k => k_ty0, tyvar_v => v_ty0 }
|
193
|
+
end
|
194
|
+
|
195
|
+
klass, singleton = recv_orig.method_dispatch_info
|
196
|
+
cur_subst = {}
|
197
|
+
scratch.generate_substitution(klass, singleton, mid, self, tmp_subst) do |subst|
|
198
|
+
cur_subst = Type.merge_substitution(cur_subst, subst)
|
199
|
+
end
|
200
|
+
|
173
201
|
found = false
|
174
202
|
aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
|
175
203
|
@sig_rets.each do |msig, ret_ty|
|
@@ -178,11 +206,10 @@ module TypeProf
|
|
178
206
|
# XXX: support self type in msig
|
179
207
|
subst = aargs.consistent_with_method_signature?(msig)
|
180
208
|
next unless subst
|
181
|
-
# need to check self tyvar?
|
182
|
-
subst[Type::Var.new(:self)] = recv
|
183
209
|
case
|
184
210
|
when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
|
185
211
|
tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
|
212
|
+
# XXX: This should be skipped when the called methods belongs to superclass
|
186
213
|
tyvars.each_with_index do |tyvar, idx|
|
187
214
|
ty = subst[tyvar]
|
188
215
|
if ty
|
@@ -192,13 +219,6 @@ module TypeProf
|
|
192
219
|
end
|
193
220
|
end
|
194
221
|
end
|
195
|
-
tyvars.zip(recv.elems.elems) do |tyvar, elem|
|
196
|
-
if subst[tyvar]
|
197
|
-
subst[tyvar] = subst[tyvar].union(elem)
|
198
|
-
else
|
199
|
-
subst[tyvar] = elem
|
200
|
-
end
|
201
|
-
end
|
202
222
|
when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
|
203
223
|
tyvar_elem = Type::Var.new(:Elem)
|
204
224
|
if subst[tyvar_elem]
|
@@ -208,16 +228,12 @@ module TypeProf
|
|
208
228
|
elems.update(nil, ty)
|
209
229
|
end
|
210
230
|
end
|
211
|
-
subst.merge!({ tyvar_elem => recv.elems.squash })
|
212
231
|
when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
|
213
232
|
tyvar_k = Type::Var.new(:K)
|
214
233
|
tyvar_v = Type::Var.new(:V)
|
215
|
-
k_ty0, v_ty0 = recv.elems.squash
|
216
234
|
if subst[tyvar_k] && subst[tyvar_v]
|
217
235
|
k_ty = subst[tyvar_k]
|
218
236
|
v_ty = subst[tyvar_v]
|
219
|
-
k_ty0 = k_ty0.union(k_ty)
|
220
|
-
v_ty0 = v_ty0.union(v_ty)
|
221
237
|
alloc_site = AllocationSite.new(caller_ep)
|
222
238
|
ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
|
223
239
|
ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
|
@@ -225,9 +241,10 @@ module TypeProf
|
|
225
241
|
elems.update(k_ty, v_ty)
|
226
242
|
end
|
227
243
|
end
|
228
|
-
# XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type?
|
229
|
-
subst.merge!({ tyvar_k => k_ty0, tyvar_v => v_ty0 })
|
230
244
|
end
|
245
|
+
subst = Type.merge_substitution(subst, cur_subst)
|
246
|
+
# need to check self tyvar?
|
247
|
+
subst[Type::Var.new(:self)] = recv
|
231
248
|
found = true
|
232
249
|
if aargs.blk_ty.is_a?(Type::Proc)
|
233
250
|
#raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
|
data/lib/typeprof/type.rb
CHANGED
@@ -170,7 +170,7 @@ module TypeProf
|
|
170
170
|
"untyped"
|
171
171
|
end
|
172
172
|
|
173
|
-
def
|
173
|
+
def method_dispatch_info
|
174
174
|
nil
|
175
175
|
end
|
176
176
|
|
@@ -430,15 +430,17 @@ module TypeProf
|
|
430
430
|
end
|
431
431
|
|
432
432
|
class Class < Type # or Module
|
433
|
-
def initialize(kind, idx, type_params, superclass, name)
|
433
|
+
def initialize(kind, idx, type_params, superclass, superclass_type_args, name)
|
434
434
|
@kind = kind # :class | :module
|
435
435
|
@idx = idx
|
436
436
|
@type_params = type_params
|
437
437
|
@superclass = superclass
|
438
|
+
raise if @kind == :class && !@superclass
|
439
|
+
@superclass_type_args = superclass_type_args
|
438
440
|
@_name = name
|
439
441
|
end
|
440
442
|
|
441
|
-
attr_reader :kind, :idx, :type_params, :superclass
|
443
|
+
attr_reader :kind, :idx, :type_params, :superclass, :superclass_type_args
|
442
444
|
|
443
445
|
def inspect
|
444
446
|
if @_name
|
@@ -452,8 +454,8 @@ module TypeProf
|
|
452
454
|
"singleton(#{ scratch.get_class_name(self) })"
|
453
455
|
end
|
454
456
|
|
455
|
-
def
|
456
|
-
|
457
|
+
def method_dispatch_info
|
458
|
+
[self, true]
|
457
459
|
end
|
458
460
|
|
459
461
|
def consistent?(other)
|
@@ -504,8 +506,8 @@ module TypeProf
|
|
504
506
|
end
|
505
507
|
end
|
506
508
|
|
507
|
-
def
|
508
|
-
|
509
|
+
def method_dispatch_info
|
510
|
+
[@klass, false]
|
509
511
|
end
|
510
512
|
|
511
513
|
def consistent?(other)
|
@@ -558,8 +560,8 @@ module TypeProf
|
|
558
560
|
end
|
559
561
|
end
|
560
562
|
|
561
|
-
def
|
562
|
-
@base_type.
|
563
|
+
def method_dispatch_info
|
564
|
+
@base_type.method_dispatch_info
|
563
565
|
end
|
564
566
|
|
565
567
|
def substitute(subst, depth)
|
@@ -600,8 +602,8 @@ module TypeProf
|
|
600
602
|
end
|
601
603
|
end
|
602
604
|
|
603
|
-
def
|
604
|
-
@base_type.
|
605
|
+
def method_dispatch_info
|
606
|
+
@base_type.method_dispatch_info
|
605
607
|
end
|
606
608
|
|
607
609
|
def substitute(_subst, _depth)
|
@@ -630,8 +632,8 @@ module TypeProf
|
|
630
632
|
@base_type
|
631
633
|
end
|
632
634
|
|
633
|
-
def
|
634
|
-
@base_type.
|
635
|
+
def method_dispatch_info
|
636
|
+
@base_type.method_dispatch_info
|
635
637
|
end
|
636
638
|
|
637
639
|
def consistent?(_other)
|
data/lib/typeprof/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Object
|
2
|
+
def foo
|
3
|
+
# The receiver is considered as an empty array
|
4
|
+
self[0]
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
# The elements are dropped when it is passed as a receiver (to avoid state explosion)
|
9
|
+
[0].foo
|
10
|
+
|
11
|
+
__END__
|
12
|
+
# Classes
|
13
|
+
class Object
|
14
|
+
def foo : -> nil
|
15
|
+
end
|
data/smoke/rbs-tyvar6.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
def log1(obj) end
|
2
|
+
def log2(obj) end
|
3
|
+
def log3(obj) end
|
4
|
+
|
5
|
+
obj = Bar.new("str")
|
6
|
+
|
7
|
+
log1(obj)
|
8
|
+
log2(obj.test_superclass)
|
9
|
+
log3(obj.test_module)
|
10
|
+
|
11
|
+
__END__
|
12
|
+
# Classes
|
13
|
+
class Object
|
14
|
+
def log1 : (Bar[String]) -> nil
|
15
|
+
def log2 : (Array[String]) -> nil
|
16
|
+
def log3 : (Integer) -> nil
|
17
|
+
end
|
data/smoke/super4.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module M1
|
2
|
+
def f(m); super :M1; end
|
3
|
+
end
|
4
|
+
module M2
|
5
|
+
def f(m); super :M2; end
|
6
|
+
end
|
7
|
+
class C
|
8
|
+
def f(m); end
|
9
|
+
end
|
10
|
+
class D < C
|
11
|
+
def f(m); super :D; end
|
12
|
+
include M1
|
13
|
+
end
|
14
|
+
class E < D
|
15
|
+
def f(m); super :E; end
|
16
|
+
include M2
|
17
|
+
end
|
18
|
+
|
19
|
+
E.new.f(:top)
|
20
|
+
|
21
|
+
__END__
|
22
|
+
# Classes
|
23
|
+
module M1
|
24
|
+
def f : (:D) -> nil
|
25
|
+
end
|
26
|
+
|
27
|
+
module M2
|
28
|
+
def f : (:E) -> nil
|
29
|
+
end
|
30
|
+
|
31
|
+
class C
|
32
|
+
def f : (:M1) -> nil
|
33
|
+
end
|
34
|
+
|
35
|
+
class D < C
|
36
|
+
include M1
|
37
|
+
def f : (:M2) -> nil
|
38
|
+
end
|
39
|
+
|
40
|
+
class E < D
|
41
|
+
include M2
|
42
|
+
def f : (:top) -> nil
|
43
|
+
end
|
data/smoke/super5.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module M
|
2
|
+
def f(m); super :M; end
|
3
|
+
end
|
4
|
+
class C
|
5
|
+
def f(m); end
|
6
|
+
end
|
7
|
+
class D < C
|
8
|
+
def f(m); super :D; end
|
9
|
+
include M
|
10
|
+
end
|
11
|
+
class E < D
|
12
|
+
def f(m); super :E; end
|
13
|
+
include M
|
14
|
+
end
|
15
|
+
|
16
|
+
E.new.f(:top)
|
17
|
+
|
18
|
+
__END__
|
19
|
+
# Classes
|
20
|
+
module M
|
21
|
+
def f : (:D | :E) -> nil
|
22
|
+
end
|
23
|
+
|
24
|
+
class C
|
25
|
+
def f : (:M) -> nil
|
26
|
+
end
|
27
|
+
|
28
|
+
class D < C
|
29
|
+
include M
|
30
|
+
def f : (:M) -> nil
|
31
|
+
end
|
32
|
+
|
33
|
+
class E < D
|
34
|
+
include M
|
35
|
+
def f : (:top) -> nil
|
36
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typeprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yusuke Endoh
|
@@ -229,6 +229,7 @@ files:
|
|
229
229
|
- smoke/optional2.rb
|
230
230
|
- smoke/optional3.rb
|
231
231
|
- smoke/parameterizedd-self.rb
|
232
|
+
- smoke/parameterizedd-self2.rb
|
232
233
|
- smoke/pathname1.rb
|
233
234
|
- smoke/pathname2.rb
|
234
235
|
- smoke/pattern-match1.rb
|
@@ -264,6 +265,8 @@ files:
|
|
264
265
|
- smoke/rbs-tyvar4.rb
|
265
266
|
- smoke/rbs-tyvar5.rb
|
266
267
|
- smoke/rbs-tyvar5.rbs
|
268
|
+
- smoke/rbs-tyvar6.rb
|
269
|
+
- smoke/rbs-tyvar6.rbs
|
267
270
|
- smoke/rbs-vars.rb
|
268
271
|
- smoke/rbs-vars.rbs
|
269
272
|
- smoke/redo1.rb
|
@@ -292,6 +295,8 @@ files:
|
|
292
295
|
- smoke/super1.rb
|
293
296
|
- smoke/super2.rb
|
294
297
|
- smoke/super3.rb
|
298
|
+
- smoke/super4.rb
|
299
|
+
- smoke/super5.rb
|
295
300
|
- smoke/svar1.rb
|
296
301
|
- smoke/symbol-proc.rb
|
297
302
|
- smoke/tap1.rb
|