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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d60066fe3965ec65f9885e311f856277d0e41330478489c026fdf6b387ba2ba
4
- data.tar.gz: 963b66fe97d98207d72645011bcd012368937ded76278d92a4b677b961c92cdc
3
+ metadata.gz: '080db9120b2b069f8a1385e3696851212a2271652f73b8627d5337d2d26d8f2b'
4
+ data.tar.gz: 969e38b2a1b64ec3fbe90551b440418901c8af028c7126b1f56acaca3818d2b1
5
5
  SHA512:
6
- metadata.gz: a40e89e05c1680480eb66798863ab99a4b38b3faaacdc471a6cdd45dfc1f897efcc8f613800ef28e5bc722c3504dec510ca943435873b6cb765a27f1bb073425
7
- data.tar.gz: 94dddf2c3e465ee19093ce571d50440293118b07ab7c90203aa5ccb40c4f9eb9afe1059eff045c965006affa8f0d66d141be2064feddf9a2b1f8384f8cadae64
6
+ metadata.gz: 322bff1d2a49e9a2729012064e393138cb9e4b81472e1c75b14a2d55a4fe3616ef3efc5ecf5df3a156a418ff6ad0281c24c2c585c61a733db0c6e4d05ceb6595
7
+ data.tar.gz: 78de3b56104b239c272938a9877bfdd49ccf20df8dbd360bf5fe7ef3c342e1d746c2adbf957fd511c03156258effe630c440941e600d58b7e7cd914ff11ca4d5
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.5.4)
4
+ typeprof (0.6.0)
5
5
  rbs (>= 0.17.0)
6
6
 
7
7
  GEM
@@ -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, superclass, absolute_path)
284
+ def initialize(kind, name, absolute_path)
285
285
  raise unless name.is_a?(Array)
286
286
  @kind = kind
287
- @superclass = superclass
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, :superclass, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
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
- # XXX: need to check if mod is already included by the ancestors?
303
- absolute_paths = @modules[singleton][mod]
304
- unless absolute_paths
305
- @modules[singleton][mod] = absolute_paths = Utils::MutableSet.new
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 get_method(mid, singleton)
323
- @methods[[singleton, mid]] || begin
324
- @modules[singleton].each_key do |mod|
325
- meth = mod.get_method(mid, false)
326
- return meth if meth
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
- nil
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
- if superclass == :__root__
377
- superclass_idx = superclass = nil
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, nil, absolute_path)
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], superclass.idx, ep.ctx.iseq.absolute_path)
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
- idx = klass.idx
436
- while idx
437
- class_def = @class_defs[idx]
438
- mthd = class_def.get_method(mid, singleton)
439
- # Need to be conservative to include all super candidates...?
440
- return mthd if mthd
441
- idx = class_def.superclass
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
- idx = ctx.cref.klass.idx
497
+ klass = ctx.cref.klass
449
498
  mid = ctx.mid
450
- idx = @class_defs[idx].superclass
451
- while idx
452
- class_def = @class_defs[idx]
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
- klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
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
- env, recv = localize_type(env.static_env.recv_ty, env, ep)
1250
- mid = ep.ctx.mid
1251
- singleton = !recv.is_a?(Type::Instance) # TODO: any?
1252
- # XXX: need to support included module...
1253
- meths = get_super_method(ep.ctx, singleton) # TODO: multiple return values
1254
- if meths
1255
- meths.each do |meth|
1256
- # XXX: this decomposition is really needed??
1257
- # It calls `Object.new` with union receiver which causes an error, but
1258
- # it may be a fault of builtin Object.new implementation.
1259
- recv.each_child do |recv|
1260
- meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
1261
- nenv, ret_ty, = localize_type(ret_ty, env, ep)
1262
- nenv = nenv.push(ret_ty)
1263
- merge_env(ep.next, nenv)
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
- meths = recv.get_method(mid, self)
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)
@@ -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
- if recv.get_method(sym, scratch)
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[type.any, ep, env]
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 = Type::Instance.new(recv).get_method(sym, scratch)
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 get_method(mid, scratch)
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 get_method(mid, scratch)
218
- @base_type.get_method(mid, scratch)
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 get_method(mid, scratch)
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 get_method(mid, scratch)
534
- @base_type.get_method(mid, scratch)
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 get_method(mid, scratch)
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 get_method(mid, scratch)
819
- @base_type.get_method(mid, scratch)
818
+ def method_dispatch_info
819
+ @base_type.method_dispatch_info
820
820
  end
821
821
  end
822
822
  end
@@ -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 = @class_defs[class_def.superclass].klass_obj == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
96
- superclass = omit ? nil : @scratch.get_class_name(@class_defs[class_def.superclass].klass_obj)
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
@@ -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
- superclass = super_class_name ? conv_type_name(super_class_name) : nil
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
- included_modules << mod
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
- extended_modules << mod
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 get_super_class_name(name, decls)
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
- return decl.super_class.name if decl.super_class
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 = cdef[:superclass]
471
- members = cdef[: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
- klass = @scratch.new_class(base_klass, name, type_params, superclass, nil)
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
- @scratch.include_module(klass, path_to_klass(mod), false, nil)
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
- @scratch.include_module(klass, path_to_klass(mod), true, nil)
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|
@@ -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
@@ -170,7 +170,7 @@ module TypeProf
170
170
  "untyped"
171
171
  end
172
172
 
173
- def get_method(mid, scratch)
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 get_method(mid, scratch)
456
- scratch.get_method(self, true, mid)
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 get_method(mid, scratch)
508
- scratch.get_method(@klass, false, mid)
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 get_method(mid, scratch)
562
- @base_type.get_method(mid, scratch)
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 get_method(mid, scratch)
604
- @base_type.get_method(mid, scratch)
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 get_method(mid, scratch)
634
- @base_type.get_method(mid, scratch)
635
+ def method_dispatch_info
636
+ @base_type.method_dispatch_info
635
637
  end
636
638
 
637
639
  def consistent?(_other)
@@ -1,3 +1,3 @@
1
1
  module TypeProf
2
- VERSION = "0.5.4"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -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
@@ -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
@@ -0,0 +1,12 @@
1
+ class Foo[X]
2
+ def test_superclass: -> X
3
+ end
4
+
5
+ module M[X]
6
+ def test_module: -> X
7
+ end
8
+
9
+ class Bar[X] < Foo[Array[X]]
10
+ def initialize: (X) -> void
11
+ include M[Integer]
12
+ end
@@ -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
@@ -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.5.4
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