typeprof 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|