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 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