typeprof 0.14.0 → 0.15.2

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: c03cc70d70c73d14871e07c098b0689e11afc8e309662a8d4402c6f2ecbc5d02
4
- data.tar.gz: '097a04710ef19e6c8f29304c901dd8569e9e74a436dd1d76a5bf515df7fdfa41'
3
+ metadata.gz: c31fc03c67fa15924e901b70890318e2391fa58cfaf897e51ff6a00d673d792a
4
+ data.tar.gz: c6ce703ec1c5f8a41d04603162746adb8a9416ccf29abc8ef1441cf83a3b41e3
5
5
  SHA512:
6
- metadata.gz: f5348942872848edec6b679db2a9afa60b746a6d3908f7066dfcd3a551d04ab728ea1494a5bdcf66867d7bc47ba0dce6ce29e2d29833babb5413262c8da92ca1
7
- data.tar.gz: 9b214f8a4a24fa433a9c3d7fb205246b161c723206a73db257eb57b3905b34ab7ef378324a7786b63daccdf763616667c2d5d6fcbaf98ff6ff455f26f956082e
6
+ metadata.gz: 790815f2528442ae742df0c3576a97ff6d2c856db374f2c8a63bb965dd6c715b6fa686d84b1fd56683e938e9c8e4014e9e86b53bb34ca4e9975b93bb5e5188df
7
+ data.tar.gz: ecc1433a74aebbe31c267c4697d71389a841cd66d74b251d1cc2d22bbeca228f141a8861ecbeebee3b16d54a8397f41eeab4f1f25ebac42103aee5e1146c9fe6
data/Gemfile.lock CHANGED
@@ -1,25 +1,25 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.13.0)
5
- rbs (>= 1.0.0)
4
+ typeprof (0.15.1)
5
+ rbs (>= 1.3.1)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  coverage-helpers (1.0.0)
11
- docile (1.3.4)
12
- power_assert (1.2.0)
11
+ docile (1.4.0)
12
+ power_assert (2.0.0)
13
13
  rake (13.0.1)
14
- rbs (1.0.3)
15
- simplecov (0.20.0)
14
+ rbs (1.3.3)
15
+ simplecov (0.21.2)
16
16
  docile (~> 1.1)
17
17
  simplecov-html (~> 0.11)
18
18
  simplecov_json_formatter (~> 0.1)
19
19
  simplecov-html (0.12.3)
20
- simplecov_json_formatter (0.1.2)
21
- stackprof (0.2.16)
22
- test-unit (3.3.7)
20
+ simplecov_json_formatter (0.1.3)
21
+ stackprof (0.2.17)
22
+ test-unit (3.4.2)
23
23
  power_assert
24
24
 
25
25
  PLATFORMS
@@ -36,4 +36,4 @@ DEPENDENCIES
36
36
  typeprof!
37
37
 
38
38
  BUNDLED WITH
39
- 2.2.3
39
+ 2.2.15
@@ -277,20 +277,23 @@ module TypeProf
277
277
  @pending_execution = {}
278
278
  @executed_iseqs = Utils::MutableSet.new
279
279
 
280
- @loaded_features = {}
280
+ @loaded_files = {}
281
281
 
282
282
  @rbs_reader = RBSReader.new
283
283
 
284
284
  @terminated = false
285
285
 
286
286
  @anonymous_struct_gen_id = 0
287
+
288
+ @types_being_shown = []
289
+ @namespace = nil
287
290
  end
288
291
 
289
292
  def add_entrypoint(iseq)
290
293
  @entrypoints << iseq
291
294
  end
292
295
 
293
- attr_reader :return_envs, :loaded_features, :rbs_reader
296
+ attr_reader :return_envs, :loaded_files, :rbs_reader
294
297
 
295
298
  def get_env(ep)
296
299
  @ep2env[ep]
@@ -329,9 +332,10 @@ module TypeProf
329
332
  @cvars = VarTable.new
330
333
  @absolute_path = absolute_path
331
334
  @namespace = nil
335
+ @subclasses = []
332
336
  end
333
337
 
334
- attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
338
+ attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path, :subclasses
335
339
  attr_accessor :name, :klass_obj
336
340
 
337
341
  def mix_module(kind, mod, type_args, singleton, absolute_path)
@@ -445,6 +449,7 @@ module TypeProf
445
449
  idx = @class_defs.size
446
450
  if superclass
447
451
  @class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
452
+ @class_defs[superclass.idx].subclasses << idx unless superclass == :__root__
448
453
  klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
449
454
  @class_defs[idx].klass_obj = klass
450
455
  cbase ||= klass # for bootstrap
@@ -471,6 +476,7 @@ module TypeProf
471
476
  superclass = Type::Builtin[:struct]
472
477
  name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
473
478
  @class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
479
+ #@class_defs[superclass.idx].subclasses << idx # needed?
474
480
  klass = Type::Class.new(:class, idx, [], superclass, name)
475
481
  add_superclass_type_args!(klass, [Type.any])
476
482
  @class_defs[idx].klass_obj = klass
@@ -526,6 +532,13 @@ module TypeProf
526
532
  end
527
533
  end
528
534
 
535
+ def traverse_subclasses(klass, &blk)
536
+ @class_defs[klass.idx].subclasses.each do |subclass|
537
+ yield @class_defs[subclass]
538
+ traverse_subclasses(@class_defs[subclass].klass_obj, &blk)
539
+ end
540
+ end
541
+
529
542
  def search_method(klass, singleton, mid, &blk)
530
543
  # XXX: support method alias correctly
531
544
  klass_orig = klass
@@ -545,7 +558,18 @@ module TypeProf
545
558
  end
546
559
  end
547
560
 
548
- def get_method(klass, singleton, mid)
561
+ def get_method(klass, singleton, include_subclasses, mid)
562
+ if include_subclasses
563
+ subclasses_mthds = []
564
+ traverse_subclasses(klass) do |subclass|
565
+ subclass.search_method(singleton, mid, {}) do |mthds,|
566
+ subclasses_mthds.concat(mthds.to_a)
567
+ end
568
+ end
569
+ search_method(klass, singleton, mid) {|mthds,| return subclasses_mthds + mthds.to_a }
570
+ return subclasses_mthds
571
+ end
572
+
549
573
  search_method(klass, singleton, mid) {|mthds,| return mthds }
550
574
  end
551
575
 
@@ -646,9 +670,10 @@ module TypeProf
646
670
  if klass == Type.any
647
671
  self
648
672
  else
649
- mdefs = get_method(klass, singleton, orig_mid)
673
+ mdefs = get_method(klass, singleton, false, orig_mid) # XXX: include_subclass == false??
650
674
  if mdefs
651
- mdefs.each do |mdef|
675
+ # dup is needed for `alias foo foo` (otherwise, "can't add a new key into hash during iteration" error occurs)
676
+ mdefs.dup.each do |mdef|
652
677
  @class_defs[klass.idx].add_method(alias_mid, singleton, AliasMethodDef.new(orig_mid, mdef, ep))
653
678
  end
654
679
  end
@@ -755,24 +780,32 @@ module TypeProf
755
780
  end
756
781
  end
757
782
 
758
- def get_ivar(recv)
783
+ def identify_class_for_ivar(recv, var)
784
+ klass, singleton = recv.method_dispatch_info
785
+ return nil unless klass
786
+ search_method(klass, singleton, var) do |mthds, klass0, singleton0|
787
+ if mthds.any? {|mthd| mthd.is_a?(AttrMethodDef) }
788
+ return klass0, singleton
789
+ end
790
+ end
791
+ return klass, singleton
792
+ end
793
+
794
+ def get_ivar(recv, var)
759
795
  recv = recv.base_type while recv.respond_to?(:base_type)
760
- case recv
761
- when Type::Class
762
- [@class_defs[recv.idx], true]
763
- when Type::Instance
764
- [@class_defs[recv.klass.idx], false]
765
- when Type::Any
766
- return
796
+
797
+ klass, singleton = identify_class_for_ivar(recv, var.to_s[1..].to_sym) # search attr_reader
798
+
799
+ if klass
800
+ return @class_defs[klass.idx], singleton
767
801
  else
768
- warn "???"
769
- return
802
+ return nil
770
803
  end
771
804
  end
772
805
 
773
806
  def add_ivar_read!(recv, var, ep, &ctn)
774
807
  recv.each_child do |recv|
775
- class_def, singleton = get_ivar(recv)
808
+ class_def, singleton = get_ivar(recv, var)
776
809
  next unless class_def
777
810
  class_def.ivars.add_read!([singleton, var], ep, &ctn)
778
811
  end
@@ -780,7 +813,7 @@ module TypeProf
780
813
 
781
814
  def add_ivar_write!(recv, var, ty, ep)
782
815
  recv.each_child do |recv|
783
- class_def, singleton = get_ivar(recv)
816
+ class_def, singleton = get_ivar(recv, var)
784
817
  next unless class_def
785
818
  class_def.ivars.add_write!([singleton, var], ty, ep, self)
786
819
  end
@@ -901,7 +934,16 @@ module TypeProf
901
934
  prologue_env = Env.new(StaticEnv.new(Type.bot, Type.nil, false, true), [], [], Utils::HashWrapper.new({}))
902
935
 
903
936
  until @entrypoints.empty?
904
- iseq = @entrypoints.shift
937
+ entrypoint = @entrypoints.shift
938
+ if entrypoint.is_a?(String)
939
+ file = entrypoint
940
+ next if @loaded_files[File.expand_path(file)]
941
+ iseq = ISeq.compile(file)
942
+ else
943
+ iseq = entrypoint
944
+ end
945
+
946
+ @loaded_files[iseq.absolute_path] = true
905
947
  ep, env = TypeProf.starting_state(iseq)
906
948
  merge_env(ep, env)
907
949
  add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| }
@@ -1077,15 +1119,16 @@ module TypeProf
1077
1119
  env = @ep2env[ep]
1078
1120
  raise "nil env" unless env
1079
1121
 
1080
- insn, operands = ep.ctx.iseq.insns[ep.pc]
1122
+ insn = ep.ctx.iseq.insns[ep.pc]
1123
+ operands = insn.operands
1081
1124
 
1082
1125
  if Config.verbose >= 2
1083
1126
  # XXX: more dedicated output
1084
1127
  puts "DEBUG: stack=%p" % [env.stack]
1085
- puts "DEBUG: %s (%s) PC=%d insn=%s sp=%d" % [ep.source_location, ep.ctx.iseq.name, ep.pc, insn, env.stack.size]
1128
+ puts "DEBUG: %s (%s) PC=%d insn=%s sp=%d" % [ep.source_location, ep.ctx.iseq.name, ep.pc, insn.insn, env.stack.size]
1086
1129
  end
1087
1130
 
1088
- case insn
1131
+ case insn.insn
1089
1132
  when :_iseq_body_start
1090
1133
  # XXX: reconstruct and record the method signature
1091
1134
  iseq = ep.ctx.iseq
@@ -1316,12 +1359,10 @@ module TypeProf
1316
1359
  when :send
1317
1360
  env, recvs, mid, aargs = setup_actual_arguments(:method, operands, ep, env)
1318
1361
  recvs = Type.any if recvs == Type.bot
1319
- recvs.each_child do |recv|
1320
- do_send(recv, mid, aargs, ep, env) do |ret_ty, ep, env|
1321
- nenv, ret_ty, = localize_type(ret_ty, env, ep)
1322
- nenv = nenv.push(ret_ty)
1323
- merge_env(ep.next, nenv)
1324
- end
1362
+ do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env|
1363
+ nenv, ret_ty, = localize_type(ret_ty, env, ep)
1364
+ nenv = nenv.push(ret_ty)
1365
+ merge_env(ep.next, nenv)
1325
1366
  end
1326
1367
  return
1327
1368
  when :recv_getlocal_send_branch
@@ -1389,24 +1430,22 @@ module TypeProf
1389
1430
  send_operands, branch_operands = operands
1390
1431
  env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env)
1391
1432
  recvs = Type.any if recvs == Type.bot
1392
- recvs.each_child do |recv|
1393
- do_send(recv, mid, aargs, ep, env) do |ret_ty, ep, env|
1394
- env, ret_ty, = localize_type(ret_ty, env, ep)
1433
+ do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env|
1434
+ env, ret_ty, = localize_type(ret_ty, env, ep)
1395
1435
 
1396
- branchtype, target, = branch_operands
1397
- # branchtype: :if or :unless or :nil
1398
- ep_then = ep.next
1399
- ep_else = ep.jump(target)
1436
+ branchtype, target, = branch_operands
1437
+ # branchtype: :if or :unless or :nil
1438
+ ep_then = ep.next
1439
+ ep_else = ep.jump(target)
1400
1440
 
1401
- case ret_ty
1402
- when Type::Instance.new(Type::Builtin[:true])
1403
- merge_env(branchtype == :if ? ep_else : ep_then, env)
1404
- when Type::Instance.new(Type::Builtin[:false])
1405
- merge_env(branchtype == :if ? ep_then : ep_else, env)
1406
- else
1407
- merge_env(ep_then, env)
1408
- merge_env(ep_else, env)
1409
- end
1441
+ case ret_ty
1442
+ when Type::Instance.new(Type::Builtin[:true])
1443
+ merge_env(branchtype == :if ? ep_else : ep_then, env)
1444
+ when Type::Instance.new(Type::Builtin[:false])
1445
+ merge_env(branchtype == :if ? ep_then : ep_else, env)
1446
+ else
1447
+ merge_env(ep_then, env)
1448
+ merge_env(ep_else, env)
1410
1449
  end
1411
1450
  end
1412
1451
  return
@@ -1440,12 +1479,10 @@ module TypeProf
1440
1479
  # XXX: this decomposition is really needed??
1441
1480
  # It calls `Object.new` with union receiver which causes an error, but
1442
1481
  # it may be a fault of builtin Object.new implementation.
1443
- recv.each_child do |recv|
1444
- meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
1445
- nenv, ret_ty, = localize_type(ret_ty, env, ep)
1446
- nenv = nenv.push(ret_ty)
1447
- merge_env(ep.next, nenv)
1448
- end
1482
+ meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
1483
+ nenv, ret_ty, = localize_type(ret_ty, env, ep)
1484
+ nenv = nenv.push(ret_ty)
1485
+ merge_env(ep.next, nenv)
1449
1486
  end
1450
1487
  end
1451
1488
  end
@@ -1606,7 +1643,7 @@ module TypeProf
1606
1643
  return
1607
1644
  end
1608
1645
 
1609
- when :getlocal, :getblockparam, :getblockparamproxy
1646
+ when :getlocal
1610
1647
  var_idx, scope_idx, _escaped = operands
1611
1648
  if scope_idx == 0
1612
1649
  ty = env.get_local(-var_idx+2)
@@ -1647,18 +1684,12 @@ module TypeProf
1647
1684
  getlocal_operands, _dup_operands, branch_operands = operands
1648
1685
  var_idx, _scope_idx, _escaped = getlocal_operands
1649
1686
  ret_ty = env.get_local(-var_idx+2)
1650
- unless ret_ty
1651
- p env.locals
1652
- raise
1653
- end
1654
1687
 
1655
1688
  branchtype, target, = branch_operands
1656
1689
  # branchtype: :if or :unless or :nil
1657
1690
  ep_then = ep.next
1658
1691
  ep_else = ep.jump(target)
1659
1692
 
1660
- var_idx, _scope_idx, _escaped = getlocal_operands
1661
-
1662
1693
  ret_ty.each_child do |ret_ty|
1663
1694
  flow_env = env.local_update(-var_idx+2, ret_ty).push(ret_ty)
1664
1695
  case ret_ty
@@ -1672,6 +1703,31 @@ module TypeProf
1672
1703
  end
1673
1704
  end
1674
1705
  return
1706
+ when :dup_setlocal_branch
1707
+ _dup_operands, setlocal_operands, branch_operands = operands
1708
+
1709
+ env, (ret_ty,) = env.pop(1)
1710
+
1711
+ var_idx, _scope_idx, _escaped = setlocal_operands
1712
+
1713
+ branchtype, target, = branch_operands
1714
+ # branchtype: :if or :unless or :nil
1715
+ ep_then = ep.next
1716
+ ep_else = ep.jump(target)
1717
+
1718
+ ret_ty.each_child do |ret_ty|
1719
+ flow_env = env.local_update(-var_idx+2, ret_ty)
1720
+ case ret_ty
1721
+ when Type.any
1722
+ merge_env(ep_then, flow_env)
1723
+ merge_env(ep_else, flow_env)
1724
+ when Type::Instance.new(Type::Builtin[:false]), Type.nil
1725
+ merge_env(branchtype == :if ? ep_then : ep_else, flow_env)
1726
+ else
1727
+ merge_env(branchtype == :if ? ep_else : ep_then, flow_env)
1728
+ end
1729
+ end
1730
+ return
1675
1731
  when :getlocal_checkmatch_branch
1676
1732
  getlocal_operands, branch_operands = operands
1677
1733
  var_idx, _scope_idx, _escaped = getlocal_operands
@@ -1935,7 +1991,7 @@ module TypeProf
1935
1991
  end
1936
1992
  env = env.push(ty)
1937
1993
  else
1938
- raise "Unknown insn: #{ insn }"
1994
+ raise "Unknown insn: #{ insn.insn }"
1939
1995
  end
1940
1996
 
1941
1997
  add_edge(ep, ep)
@@ -2133,30 +2189,32 @@ module TypeProf
2133
2189
  return env, recv, mid, aargs
2134
2190
  end
2135
2191
 
2136
- def do_send(recv, mid, aargs, ep, env, &ctn)
2137
- case recv
2138
- when Type::Void
2139
- error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2140
- ctn[Type.any, ep, env]
2141
- when Type::Any
2142
- ctn[Type.any, ep, env]
2143
- else
2144
- klass, singleton = recv.method_dispatch_info
2145
- meths = get_method(klass, singleton, mid) if klass
2146
- if meths
2147
- meths.each do |meth|
2148
- meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
2149
- end
2192
+ def do_send(recvs, mid, aargs, ep, env, &ctn)
2193
+ recvs.each_child do |recv|
2194
+ case recv
2195
+ when Type::Void
2196
+ error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2197
+ ctn[Type.any, ep, env]
2198
+ when Type::Any
2199
+ ctn[Type.any, ep, env]
2150
2200
  else
2151
- meths = get_method(klass, singleton, :method_missing) if klass
2201
+ klass, singleton, include_subclasses = recv.method_dispatch_info
2202
+ meths = get_method(klass, singleton, include_subclasses, mid) if klass
2152
2203
  if meths
2153
- aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
2154
2204
  meths.each do |meth|
2155
- meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
2205
+ meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
2156
2206
  end
2157
2207
  else
2158
- error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2159
- ctn[Type.any, ep, env]
2208
+ meths = get_method(klass, singleton, include_subclasses, :method_missing) if klass
2209
+ if meths
2210
+ aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
2211
+ meths.each do |meth|
2212
+ meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
2213
+ end
2214
+ else
2215
+ error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2216
+ ctn[Type.any, ep, env]
2217
+ end
2160
2218
  end
2161
2219
  end
2162
2220
  end
@@ -2167,7 +2225,7 @@ module TypeProf
2167
2225
  if blk.is_a?(Type::Proc)
2168
2226
  blk.block_body.do_call(aargs, ep, env, self, replace_recv_ty: replace_recv_ty, replace_cref: replace_cref, &ctn)
2169
2227
  else
2170
- warn(ep, "non-proc is passed as a block")
2228
+ warn(ep, "non-proc is passed as a block") if blk != Type.any
2171
2229
  ctn[Type.any, ep, env]
2172
2230
  end
2173
2231
  end
@@ -2241,7 +2299,11 @@ module TypeProf
2241
2299
  next unless @block_to_ctx[blk.block_body] # this occurs when screen_name is called before type-profiling finished (e.g., error message)
2242
2300
  @block_to_ctx[blk.block_body].each do |blk_ctx|
2243
2301
  if farg_tys
2244
- farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx])
2302
+ if @method_signatures[blk_ctx]
2303
+ farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx])
2304
+ else
2305
+ # this occurs when screen_name is called before type-profiling finished (e.g., error message)
2306
+ end
2245
2307
  else
2246
2308
  farg_tys = @method_signatures[blk_ctx]
2247
2309
  end
@@ -2251,17 +2313,24 @@ module TypeProf
2251
2313
  end
2252
2314
  end
2253
2315
 
2254
- farg_tys = farg_tys ? farg_tys.screen_name(nil, self) : "(unknown)"
2255
- ret_ty = ret_ty.screen_name(self)
2256
- ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
2316
+ return Type.any.screen_name(self) if @types_being_shown.include?(farg_tys) || @types_being_shown.include?(ret_ty)
2257
2317
 
2258
- farg_tys = farg_tys + " " if farg_tys != ""
2259
- "^#{ farg_tys }-> #{ ret_ty }"
2318
+ begin
2319
+ @types_being_shown << farg_tys << ret_ty
2320
+ farg_tys = farg_tys ? farg_tys.screen_name(nil, self) : "(unknown)"
2321
+ ret_ty = ret_ty.screen_name(self)
2322
+ ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
2323
+
2324
+ farg_tys = farg_tys + " " if farg_tys != ""
2325
+ "^#{ farg_tys }-> #{ ret_ty }"
2326
+ ensure
2327
+ @types_being_shown.pop(2)
2328
+ end
2260
2329
  end
2261
2330
 
2262
2331
  def show_method_signature(ctx)
2263
2332
  farg_tys = @method_signatures[ctx]
2264
- ret_ty = @return_values[ctx] || Type.bot
2333
+ ret_ty = ctx.mid == :initialize ? Type::Void.new : @return_values[ctx] || Type.bot
2265
2334
 
2266
2335
  untyped = farg_tys.include_untyped?(self) || ret_ty.include_untyped?(self)
2267
2336