typeprof 0.4.2 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -2
  3. data/Gemfile.lock +3 -3
  4. data/README.md +6 -0
  5. data/lib/typeprof/analyzer.rb +97 -84
  6. data/lib/typeprof/arguments.rb +27 -19
  7. data/lib/typeprof/block.rb +5 -2
  8. data/lib/typeprof/builtin.rb +14 -4
  9. data/lib/typeprof/config.rb +10 -6
  10. data/lib/typeprof/container-type.rb +117 -101
  11. data/lib/typeprof/export.rb +1 -1
  12. data/lib/typeprof/import.rb +44 -22
  13. data/lib/typeprof/method.rb +70 -12
  14. data/lib/typeprof/type.rb +108 -89
  15. data/lib/typeprof/version.rb +1 -1
  16. data/smoke/arguments2.rb +1 -1
  17. data/smoke/array11.rb +1 -1
  18. data/smoke/array6.rb +2 -2
  19. data/smoke/array8.rb +1 -1
  20. data/smoke/block-args2.rb +3 -3
  21. data/smoke/block-args3.rb +4 -4
  22. data/smoke/block-blockarg.rb +1 -1
  23. data/smoke/block-kwarg.rb +1 -1
  24. data/smoke/block10.rb +1 -1
  25. data/smoke/block5.rb +1 -1
  26. data/smoke/constant2.rb +1 -2
  27. data/smoke/demo5.rb +1 -1
  28. data/smoke/demo9.rb +1 -1
  29. data/smoke/hash-fetch.rb +3 -3
  30. data/smoke/hash-merge-bang.rb +11 -0
  31. data/smoke/hash1.rb +3 -2
  32. data/smoke/hash3.rb +1 -1
  33. data/smoke/inheritance2.rb +2 -2
  34. data/smoke/ivar2.rb +2 -2
  35. data/smoke/kernel-class.rb +1 -1
  36. data/smoke/keyword4.rb +1 -1
  37. data/smoke/kwsplat1.rb +2 -2
  38. data/smoke/kwsplat2.rb +1 -1
  39. data/smoke/multiple-superclass.rb +1 -1
  40. data/smoke/parameterizedd-self.rb +2 -2
  41. data/smoke/pattern-match1.rb +23 -0
  42. data/smoke/pattern-match2.rb +15 -0
  43. data/smoke/rbs-tyvar3.rb +11 -19
  44. data/smoke/rbs-tyvar3.rbs +4 -3
  45. data/smoke/rbs-tyvar4.rb +36 -0
  46. data/smoke/rbs-tyvar5.rb +12 -0
  47. data/smoke/rbs-tyvar5.rbs +8 -0
  48. data/smoke/struct.rb +2 -2
  49. data/smoke/uninitialize-var.rb +12 -0
  50. data/smoke/union-recv.rb +2 -2
  51. data/typeprof.gemspec +1 -1
  52. metadata +11 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2ffa092b1a33661649a9a3b48347d78baf5d9bac0ba4020f72a122442d4d287
4
- data.tar.gz: fbe985ca3547bd831564f5921f38edf65160c86133bb0219596aaa4e5962066a
3
+ metadata.gz: 2d60066fe3965ec65f9885e311f856277d0e41330478489c026fdf6b387ba2ba
4
+ data.tar.gz: 963b66fe97d98207d72645011bcd012368937ded76278d92a4b677b961c92cdc
5
5
  SHA512:
6
- metadata.gz: b260426c710befa65825fc41998643ced8ef3b43d4edc16b5eb9a2f00cbaf865c832f80ee3443c6a8e9f725e5def2d6bd47a1109e97dffaab8d17771035ae08a
7
- data.tar.gz: 47cf9f339601864c16464859d92aa9b904e51c471da84c2f2997519947edbc9c647b1762129cc0d677264fe0c0372de56acf04e98968a7b6e1c372d43af8a543
6
+ metadata.gz: a40e89e05c1680480eb66798863ab99a4b38b3faaacdc471a6cdd45dfc1f897efcc8f613800ef28e5bc722c3504dec510ca943435873b6cb765a27f1bb073425
7
+ data.tar.gz: 94dddf2c3e465ee19093ce571d50440293118b07ab7c90203aa5ccb40c4f9eb9afe1059eff045c965006affa8f0d66d141be2064feddf9a2b1f8384f8cadae64
@@ -17,9 +17,8 @@ jobs:
17
17
  uses: ruby/setup-ruby@v1
18
18
  with:
19
19
  ruby-version: ${{ matrix.ruby-version }}
20
- - name: Set up RBS and bundle install
20
+ - name: Bundle install
21
21
  run: |
22
- cd rbs && bundle install && bundle exec rake parser && cd ..
23
22
  bundle install
24
23
  - name: Run the test suite
25
24
  run: |
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.4.1)
5
- rbs (>= 0.16.0)
4
+ typeprof (0.5.4)
5
+ rbs (>= 0.17.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -11,7 +11,7 @@ GEM
11
11
  docile (1.3.2)
12
12
  power_assert (1.2.0)
13
13
  rake (13.0.1)
14
- rbs (0.16.0)
14
+ rbs (0.17.0)
15
15
  simplecov (0.19.1)
16
16
  docile (~> 1.1)
17
17
  simplecov-html (~> 0.11)
data/README.md CHANGED
@@ -33,3 +33,9 @@ end
33
33
  ## Documentation
34
34
 
35
35
  [English](doc/doc.md) / [日本語](doc/doc.ja.md)
36
+
37
+ ## Playground
38
+
39
+ You can try typeprof gem on the Web via the URL below.
40
+
41
+ https://mame.github.io/typeprof-playground/
@@ -87,6 +87,11 @@ module TypeProf
87
87
  @recv_ty = recv_ty
88
88
  @blk_ty = blk_ty
89
89
  @mod_func = mod_func
90
+
91
+ return if recv_ty == :top #OK
92
+ recv_ty.each_child_global do |ty|
93
+ raise ty.inspect if !ty.is_a?(Type::Instance) && !ty.is_a?(Type::Class) && ty != Type.any
94
+ end
90
95
  end
91
96
 
92
97
  attr_reader :recv_ty, :blk_ty, :mod_func
@@ -129,11 +134,7 @@ module TypeProf
129
134
  elems2 = type_params[id]
130
135
  if elems2
131
136
  if elems != elems2
132
- if elems.is_a?(Array) # should be refactored as Cell::Elements
133
- type_params[id] = elems.zip(elems2).map {|elem1, elem2| elem1.union(elem2) }
134
- else
135
- type_params[id] = elems.union(elems2)
136
- end
137
+ type_params[id] = elems.union(elems2)
137
138
  end
138
139
  else
139
140
  type_params[id] = elems
@@ -151,6 +152,8 @@ module TypeProf
151
152
  tys.each do |ty|
152
153
  raise "nil cannot be pushed to the stack" if ty.nil?
153
154
  ty.each_child do |ty|
155
+ raise if ty.is_a?(Type::Var)
156
+ #raise if ty.is_a?(Type::Instance) && ty.klass.type_params.size > 1
154
157
  raise "Array cannot be pushed to the stack" if ty.is_a?(Type::Array)
155
158
  raise "Hash cannot be pushed to the stack" if ty.is_a?(Type::Hash)
156
159
  end
@@ -249,6 +252,8 @@ module TypeProf
249
252
  @rbs_reader = RBSReader.new
250
253
 
251
254
  @terminated = false
255
+
256
+ @anonymous_struct_gen_id = 0
252
257
  end
253
258
 
254
259
  attr_reader :return_envs, :loaded_features, :rbs_reader
@@ -293,20 +298,11 @@ module TypeProf
293
298
  attr_reader :kind, :superclass, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
294
299
  attr_accessor :name, :klass_obj
295
300
 
296
- def include_module(mod, absolute_path)
297
- # XXX: need to check if mod is already included by the ancestors?
298
- absolute_paths = @modules[false][mod]
299
- unless absolute_paths
300
- @modules[false][mod] = absolute_paths = Utils::MutableSet.new
301
- end
302
- absolute_paths << absolute_path
303
- end
304
-
305
- def extend_module(mod, absolute_path)
301
+ def include_module(mod, singleton, absolute_path)
306
302
  # XXX: need to check if mod is already included by the ancestors?
307
- absolute_paths = @modules[true][mod]
303
+ absolute_paths = @modules[singleton][mod]
308
304
  unless absolute_paths
309
- @modules[true][mod] = absolute_paths = Utils::MutableSet.new
305
+ @modules[singleton][mod] = absolute_paths = Utils::MutableSet.new
310
306
  end
311
307
  absolute_paths << absolute_path
312
308
  end
@@ -353,7 +349,7 @@ module TypeProf
353
349
  end
354
350
  end
355
351
 
356
- def include_module(including_mod, included_mod, absolute_path)
352
+ def include_module(including_mod, included_mod, singleton, absolute_path)
357
353
  return if included_mod == Type.any
358
354
 
359
355
  including_mod = @class_defs[including_mod.idx]
@@ -361,7 +357,7 @@ module TypeProf
361
357
  if included_mod.is_a?(Type::Class)
362
358
  included_mod = @class_defs[included_mod.idx]
363
359
  if included_mod && included_mod.kind == :module
364
- including_mod.include_module(included_mod, absolute_path)
360
+ including_mod.include_module(included_mod, singleton, absolute_path)
365
361
  else
366
362
  warn "including something that is not a module"
367
363
  end
@@ -369,20 +365,6 @@ module TypeProf
369
365
  end
370
366
  end
371
367
 
372
- def extend_module(extending_mod, extended_mod, absolute_path)
373
- extending_mod = @class_defs[extending_mod.idx]
374
- extended_mod.each_child do |extended_mod|
375
- if extended_mod.is_a?(Type::Class)
376
- extended_mod = @class_defs[extended_mod.idx]
377
- if extended_mod && extended_mod.kind == :module
378
- extending_mod.extend_module(extended_mod, absolute_path)
379
- else
380
- warn "extending something that is not a module"
381
- end
382
- end
383
- end
384
- end
385
-
386
368
  def cbase_path(cbase)
387
369
  cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
388
370
  end
@@ -417,8 +399,9 @@ module TypeProf
417
399
 
418
400
  idx = @class_defs.size
419
401
  superclass = Type::Builtin[:struct]
420
- @class_defs[idx] = ClassDef.new(:class, ["(Anonymous Struct)"], superclass.idx, ep.ctx.iseq.absolute_path)
421
- klass = Type::Class.new(:class, idx, [], superclass, "(Anonymous Struct)")
402
+ 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)
422
405
  @class_defs[idx].klass_obj = klass
423
406
 
424
407
  @struct_defs[ep] = klass
@@ -572,9 +555,7 @@ module TypeProf
572
555
 
573
556
  ret_ty = @return_values[callee_ctx] ||= Type.bot
574
557
  if ret_ty != Type.bot
575
- @callsites[callee_ctx].each do |caller_ep, ctn|
576
- ctn[ret_ty, caller_ep, @return_envs[caller_ep]]
577
- end
558
+ ctn[ret_ty, caller_ep, @return_envs[caller_ep]]
578
559
  end
579
560
  end
580
561
 
@@ -632,7 +613,7 @@ module TypeProf
632
613
  entry = @tbl[site] ||= Entry.new(!ep, {}, Type.bot, Utils::MutableSet.new)
633
614
  if ep
634
615
  if entry.rbs_declared
635
- if !entry.type.consistent?(ty, {})
616
+ unless Type.match?(ty, entry.type)
636
617
  scratch.warn(ep, "inconsistent assignment to RBS-declared global variable")
637
618
  return
638
619
  end
@@ -651,6 +632,7 @@ module TypeProf
651
632
  end
652
633
 
653
634
  def get_ivar(recv)
635
+ recv = recv.base_type while recv.respond_to?(:base_type)
654
636
  case recv
655
637
  when Type::Class
656
638
  [@class_defs[recv.idx], true]
@@ -884,26 +866,41 @@ module TypeProf
884
866
  def pend_method_execution(iseq, meth, recv, mid, cref)
885
867
  ctx = Context.new(iseq, cref, mid)
886
868
  ep = ExecutionPoint.new(ctx, 0, nil)
887
- locals = [Type.any] * iseq.locals.size
888
-
889
- keyword = iseq.fargs_format[:keyword]
869
+ locals = [Type.nil] * iseq.locals.size
870
+
871
+ fargs_format = iseq.fargs_format
872
+ lead_num = fargs_format[:lead_num] || 0
873
+ post_num = fargs_format[:post_num] || 0
874
+ post_index = fargs_format[:post_start]
875
+ rest_index = fargs_format[:rest_start]
876
+ keyword = fargs_format[:keyword]
877
+ kw_index = fargs_format[:kwbits] - keyword.size if keyword
878
+ kwrest_index = fargs_format[:kwrest]
879
+ block_index = fargs_format[:block_start]
880
+ opt = fargs_format[:opt] || [0]
881
+
882
+ (lead_num + opt.size - 1).times {|i| locals[i] = Type.any }
883
+ post_num.times {|i| locals[i + post_index] = Type.any } if post_index
884
+ locals[rest_index] = Type.any if rest_index
890
885
  if keyword
891
- kw_start = iseq.fargs_format[:kwbits]
892
- kw_start -= iseq.fargs_format[:keyword].size if kw_start
893
886
  keyword.each_with_index do |kw, i|
894
887
  case
895
888
  when kw.is_a?(Symbol) # required keyword
889
+ locals[kw_index + i] = Type.any
896
890
  when kw.size == 2 # optional keyword (default value is a literal)
897
891
  _key, default_ty = *kw
898
892
  default_ty = Type.guess_literal_type(default_ty)
899
- default_ty = default_ty.type if default_ty.is_a?(Type::Literal)
900
- locals[kw_start + i] = default_ty.union(Type.any)
893
+ default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal)
894
+ locals[kw_index + i] = default_ty.union(Type.any)
901
895
  else # optional keyword (default value is an expression)
896
+ locals[kw_index + i] = Type.any
902
897
  end
903
898
  end
904
899
  end
900
+ locals[kwrest_index] = Type.any if kwrest_index
901
+ locals[block_index] = Type.nil if block_index
905
902
 
906
- env = Env.new(StaticEnv.new(recv, Type.any, false), locals, [], Utils::HashWrapper.new({}))
903
+ env = Env.new(StaticEnv.new(recv, Type.nil, false), locals, [], Utils::HashWrapper.new({}))
907
904
 
908
905
  @pending_execution[iseq] ||= [:method, [meth, ep, env]]
909
906
  end
@@ -986,7 +983,7 @@ module TypeProf
986
983
  when kw.size == 2 # optional keyword (default value is a literal)
987
984
  key, default_ty = *kw
988
985
  default_ty = Type.guess_literal_type(default_ty)
989
- default_ty = default_ty.type if default_ty.is_a?(Type::Literal)
986
+ default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal)
990
987
  req = false
991
988
  else # optional keyword (default value is an expression)
992
989
  key, = kw
@@ -1029,7 +1026,17 @@ module TypeProf
1029
1026
  ty = Type::Literal.new(str, Type::Instance.new(Type::Builtin[:str]))
1030
1027
  env = env.push(ty)
1031
1028
  when :putself
1032
- env, ty = localize_type(env.static_env.recv_ty, env, ep)
1029
+ ty = env.static_env.recv_ty
1030
+ if ty.is_a?(Type::Instance)
1031
+ klass = ty.klass
1032
+ if klass.type_params.size >= 1
1033
+ ty = Type::ContainerType.create_empty_instance(klass)
1034
+ env, ty = localize_type(ty, env, ep, AllocationSite.new(ep))
1035
+ else
1036
+ ty = Type::Instance.new(klass)
1037
+ end
1038
+ env, ty = localize_type(ty, env, ep)
1039
+ end
1033
1040
  env = env.push(ty)
1034
1041
  when :newarray, :newarraykwsplat
1035
1042
  len, = operands
@@ -1128,35 +1135,29 @@ module TypeProf
1128
1135
  else
1129
1136
  if existing_klass != Type.any
1130
1137
  error(ep, "the class \"#{ id }\" is #{ existing_klass.screen_name(self) }")
1131
- id = :"#{ id }(dummy)"
1132
1138
  end
1133
- existing_klass = get_constant(cbase, id) # TODO: multiple return values
1134
- if existing_klass != Type.any
1135
- klass = existing_klass
1136
- else
1137
- if type == :class
1138
- if superclass.is_a?(Type::Class)
1139
- # okay
1140
- elsif superclass == Type.any
1141
- warn(ep, "superclass is any; Object is used instead")
1142
- superclass = Type::Builtin[:obj]
1143
- elsif superclass == Type.nil
1144
- superclass = Type::Builtin[:obj]
1145
- elsif superclass.is_a?(Type::Instance)
1146
- warn(ep, "superclass is an instance; Object is used instead")
1147
- superclass = Type::Builtin[:obj]
1148
- else
1149
- warn(ep, "superclass is not a class; Object is used instead")
1150
- superclass = Type::Builtin[:obj]
1151
- end
1152
- else # module
1153
- superclass = nil
1154
- end
1155
- if cbase == Type.any
1156
- klass = Type.any
1139
+ if type == :class
1140
+ if superclass.is_a?(Type::Class)
1141
+ # okay
1142
+ elsif superclass == Type.any
1143
+ warn(ep, "superclass is any; Object is used instead")
1144
+ superclass = Type::Builtin[:obj]
1145
+ elsif superclass == Type.nil
1146
+ superclass = Type::Builtin[:obj]
1147
+ elsif superclass.is_a?(Type::Instance)
1148
+ warn(ep, "superclass is an instance; Object is used instead")
1149
+ superclass = Type::Builtin[:obj]
1157
1150
  else
1158
- klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
1151
+ warn(ep, "superclass is not a class; Object is used instead")
1152
+ superclass = Type::Builtin[:obj]
1159
1153
  end
1154
+ else # module
1155
+ superclass = nil
1156
+ end
1157
+ if cbase == Type.any
1158
+ klass = Type.any
1159
+ else
1160
+ klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
1160
1161
  end
1161
1162
  end
1162
1163
  singleton = false
@@ -1700,15 +1701,27 @@ module TypeProf
1700
1701
  end
1701
1702
 
1702
1703
  when :checktype
1703
- type, = operands
1704
- raise NotImplementedError if type != 5 # T_STRING
1705
- # XXX: is_a?
1706
- env, (val,) = env.pop(1)
1707
- res = globalize_type(val, env, ep) == Type::Instance.new(Type::Builtin[:str])
1708
- if res
1709
- ty = Type::Instance.new(Type::Builtin[:true])
1704
+ kind, = operands
1705
+ case kind
1706
+ when 5 then klass = :str # T_STRING
1707
+ when 7 then klass = :ary # T_ARRAY
1708
+ when 8 then klass = :hash # T_HASH
1710
1709
  else
1711
- ty = Type::Instance.new(Type::Builtin[:false])
1710
+ raise NotImplementedError
1711
+ end
1712
+ env, (val,) = env.pop(1)
1713
+ ty = Type.bot
1714
+ val.each_child do |val|
1715
+ #globalize_type(val, env, ep).each_child_global do |val|
1716
+ val = val.base_type while val.respond_to?(:base_type)
1717
+ case val
1718
+ when Type::Instance.new(Type::Builtin[klass])
1719
+ ty = ty.union(Type::Instance.new(Type::Builtin[:true]))
1720
+ when Type.any
1721
+ ty = Type.bool
1722
+ else
1723
+ ty = ty.union(Type::Instance.new(Type::Builtin[:false]))
1724
+ end
1712
1725
  end
1713
1726
  env = env.push(ty)
1714
1727
  else
@@ -1946,7 +1959,7 @@ module TypeProf
1946
1959
  end
1947
1960
  end
1948
1961
 
1949
- @block_to_ctx[blk.block_body].each do |blk_ctx|
1962
+ @block_to_ctx[blk.block_body]&.each do |blk_ctx|
1950
1963
  ret_ty = ret_ty.union(@return_values[blk_ctx]) if @return_values[blk_ctx]
1951
1964
  end
1952
1965
  end
@@ -25,7 +25,7 @@ module TypeProf
25
25
  self
26
26
  end
27
27
 
28
- def consistent_with_method_signature?(msig, subst)
28
+ def consistent_with_method_signature?(msig)
29
29
  aargs = @lead_tys.dup
30
30
 
31
31
  # aargs: lead_tys, rest_ty
@@ -36,53 +36,61 @@ module TypeProf
36
36
  (lower_bound..upper_bound).each do |n|
37
37
  # BUG: @rest_ty is an Array, so need to squash
38
38
  tmp_aargs = ActualArguments.new(@lead_tys + [@rest_ty] * n, nil, @kw_tys, @blk_ty)
39
- if tmp_aargs.consistent_with_method_signature?(msig, subst) # XXX: wrong subst handling in the loop!
40
- return true
41
- end
39
+ subst = tmp_aargs.consistent_with_method_signature?(msig) # XXX: wrong subst handling in the loop!
40
+ return subst if subst
42
41
  end
43
- return false
42
+ return nil
44
43
  end
45
44
 
45
+ subst = {}
46
46
  if msig.rest_ty
47
- return false if aargs.size < msig.lead_tys.size + msig.post_tys.size
47
+ return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size
48
48
  aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg|
49
- return false unless aarg.consistent?(farg, subst)
49
+ return nil unless subst2 = Type.match?(aarg, farg)
50
+ subst = Type.merge_substitution(subst, subst2)
50
51
  end
51
52
  aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg|
52
- return false unless aarg.consistent?(farg, subst)
53
+ return nil unless subst2 = Type.match?(aarg, farg)
54
+ subst = Type.merge_substitution(subst, subst2)
53
55
  end
54
56
  msig.opt_tys.each do |farg|
55
57
  aarg = aargs.shift
56
- return false unless aarg.consistent?(farg, subst)
58
+ return nil unless subst2 = Type.match?(aarg, farg)
59
+ subst = Type.merge_substitution(subst, subst2)
57
60
  end
58
61
  aargs.each do |aarg|
59
- return false unless aarg.consistent?(msig.rest_ty, subst)
62
+ return nil unless subst2 = Type.match?(aarg, msig.rest_ty)
63
+ subst = Type.merge_substitution(subst, subst2)
60
64
  end
61
65
  else
62
- return false if aargs.size < msig.lead_tys.size + msig.post_tys.size
63
- return false if aargs.size > msig.lead_tys.size + msig.post_tys.size + msig.opt_tys.size
66
+ return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size
67
+ return nil if aargs.size > msig.lead_tys.size + msig.post_tys.size + msig.opt_tys.size
64
68
  aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg|
65
- return false unless aarg.consistent?(farg, subst)
69
+ return nil unless subst2 = Type.match?(aarg, farg)
70
+ subst = Type.merge_substitution(subst, subst2)
66
71
  end
67
72
  aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg|
68
- return false unless aarg.consistent?(farg, subst)
73
+ return nil unless subst2 = Type.match?(aarg, farg)
74
+ subst = Type.merge_substitution(subst, subst2)
69
75
  end
70
76
  aargs.zip(msig.opt_tys) do |aarg, farg|
71
- return false unless aarg.consistent?(farg, subst)
77
+ return nil unless subst2 = Type.match?(aarg, farg)
78
+ subst = Type.merge_substitution(subst, subst2)
72
79
  end
73
80
  end
74
81
  # XXX: msig.keyword_tys
75
82
 
76
83
  case msig.blk_ty
77
84
  when Type::Proc
78
- return false if @blk_ty == Type.nil
85
+ return nil if @blk_ty == Type.nil
79
86
  when Type.nil
80
- return false if @blk_ty != Type.nil
87
+ return nil if @blk_ty != Type.nil
81
88
  when Type::Any
82
89
  else
83
90
  raise "unknown type of formal block signature"
84
91
  end
85
- true
92
+
93
+ subst
86
94
  end
87
95
 
88
96
  def argument_error(given, exp_lower, exp_upper)
@@ -345,7 +353,7 @@ module TypeProf
345
353
  when kw.size == 2 # optional keyword (default value is a literal)
346
354
  key, default_ty = *kw
347
355
  default_ty = Type.guess_literal_type(default_ty)
348
- default_ty = default_ty.type if default_ty.is_a?(Type::Literal)
356
+ default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal)
349
357
  req = false
350
358
  else # optional keyword (default value is an expression)
351
359
  key, = kw