typeprof 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -139,7 +139,7 @@ module TypeProf
139
139
  iseq_methods[method_name] << @scratch.show_method_signature(ctx)
140
140
  end
141
141
  when AttrMethodDef
142
- next if Config.check_dir_filter(mdef.absolute_path) == :exclude
142
+ next if !mdef.absolute_path || Config.check_dir_filter(mdef.absolute_path) == :exclude
143
143
  mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
144
144
  method_name = mid
145
145
  method_name = "self.#{ mid }" if singleton
@@ -168,12 +168,14 @@ module TypeProf
168
168
  next unless var.to_s.start_with?("@")
169
169
  var = "self.#{ var }" if singleton
170
170
  next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
171
- [var, ty.screen_name(@scratch), entry.rbs_declared]
171
+ next if entry.rbs_declared
172
+ [var, ty.screen_name(@scratch)]
172
173
  end.compact
173
174
 
174
175
  cvars = cvars.map do |var, entry|
175
176
  next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
176
- [var, entry.type.screen_name(@scratch), entry.rbs_declared]
177
+ next if entry.rbs_declared
178
+ [var, entry.type.screen_name(@scratch)]
177
179
  end.compact
178
180
 
179
181
  if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
@@ -277,14 +279,12 @@ module TypeProf
277
279
  output.puts indent + " extend #{ mod }"
278
280
  first = false
279
281
  end
280
- class_data.ivars.each do |var, ty, rbs_declared|
281
- s = rbs_declared ? "# " : " "
282
- output.puts indent + s + "#{ var } : #{ ty }" unless var.start_with?("_")
282
+ class_data.ivars.each do |var, ty|
283
+ output.puts indent + " #{ var } : #{ ty }" unless var.start_with?("_")
283
284
  first = false
284
285
  end
285
- class_data.cvars.each do |var, ty, rbs_declared|
286
- s = rbs_declared ? "# " : " "
287
- output.puts indent + s + "#{ var } : #{ ty }"
286
+ class_data.cvars.each do |var, ty|
287
+ output.puts indent + " #{ var } : #{ ty }"
288
288
  first = false
289
289
  end
290
290
  class_data.attr_methods.each do |(method_name, hidden), (kind, ty)|
@@ -113,6 +113,7 @@ module TypeProf
113
113
  included_modules = []
114
114
  extended_modules = []
115
115
  methods = {}
116
+ attr_methods = {}
116
117
  ivars = {}
117
118
  cvars = {}
118
119
  rbs_sources = {}
@@ -148,15 +149,15 @@ module TypeProf
148
149
  end
149
150
  when RBS::AST::Members::AttrReader
150
151
  ty = conv_type(member.type)
151
- methods[[false, member.name]] = attr_reader_def(ty)
152
+ attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
152
153
  when RBS::AST::Members::AttrWriter
153
154
  ty = conv_type(member.type)
154
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
155
+ attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
155
156
  when RBS::AST::Members::AttrAccessor
156
157
  ty = conv_type(member.type)
157
- methods[[false, member.name]] = attr_reader_def(ty)
158
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
158
+ attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
159
159
  when RBS::AST::Members::Alias
160
+ # XXX: an alias to attr methods?
160
161
  if member.instance?
161
162
  method_def = methods[[false, member.old_name]]
162
163
  methods[[false, member.new_name]] = method_def if method_def
@@ -212,6 +213,7 @@ module TypeProf
212
213
  included_modules: included_modules,
213
214
  extended_modules: extended_modules,
214
215
  methods: methods,
216
+ attr_methods: attr_methods,
215
217
  ivars: ivars,
216
218
  cvars: cvars,
217
219
  rbs_sources: rbs_sources,
@@ -308,7 +310,7 @@ module TypeProf
308
310
  opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
309
311
  req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
310
312
  rest_kw_ty = func.rest_keywords
311
- raise NotImplementedError if rest_kw_ty # XXX
313
+ rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
312
314
 
313
315
  ret_ty = conv_type(func.return_type)
314
316
 
@@ -325,32 +327,12 @@ module TypeProf
325
327
  }
326
328
  end
327
329
 
328
- def attr_reader_def(ty)
329
- [{
330
- type_params: [],
331
- lead_tys: [],
332
- opt_tys: [],
333
- rest_ty: nil,
334
- req_kw_tys: {},
335
- opt_kw_tys: {},
336
- rest_kw_ty: nil,
337
- blk: nil,
338
- ret_ty: ty,
339
- }]
340
- end
341
-
342
- def attr_writer_def(ty)
343
- [{
344
- type_params: [],
345
- lead_tys: [ty],
346
- opt_tys: [],
347
- rest_ty: nil,
348
- req_kw_tys: {},
349
- opt_kw_tys: {},
350
- rest_kw_ty: nil,
351
- blk: nil,
352
- ret_ty: ty,
353
- }]
330
+ def attr_method_def(kind, name, ty)
331
+ {
332
+ kind: kind,
333
+ ivar: name,
334
+ ty: ty,
335
+ }
354
336
  end
355
337
 
356
338
  def conv_block(rbs_block)
@@ -518,6 +500,7 @@ module TypeProf
518
500
  included_modules = members[:included_modules]
519
501
  extended_modules = members[:extended_modules]
520
502
  methods = members[:methods]
503
+ attr_methods = members[:attr_methods]
521
504
  ivars = members[:ivars]
522
505
  cvars = members[:cvars]
523
506
  rbs_sources = members[:rbs_sources]
@@ -538,6 +521,14 @@ module TypeProf
538
521
  @scratch.add_method(klass, method_name, singleton, mdef)
539
522
  end
540
523
 
524
+ attr_methods.each do |(singleton, method_name), mdef|
525
+ kind = mdef[:kind]
526
+ ivar = mdef[:ivar]
527
+ ty = conv_type(mdef[:ty]).remove_type_vars
528
+ @scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
529
+ @scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
530
+ end
531
+
541
532
  ivars.each do |ivar_name, ty|
542
533
  ty = conv_type(ty).remove_type_vars
543
534
  @scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
@@ -604,7 +595,7 @@ module TypeProf
604
595
  req, lead_tys, opt_tys, ret_ty = blk
605
596
  lead_tys = lead_tys.map {|ty| conv_type(ty) }
606
597
  opt_tys = opt_tys.map {|ty| conv_type(ty) }
607
- msig = MethodSignature.new(lead_tys, opt_tys, nil, nil, nil, nil, nil)
598
+ msig = MethodSignature.new(lead_tys, opt_tys, nil, [], {}, nil, Type.nil)
608
599
  ret_ty = conv_type(ret_ty)
609
600
  ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
610
601
  ret << Type.nil unless req
@@ -4,10 +4,11 @@ module TypeProf
4
4
  end
5
5
 
6
6
  class ISeqMethodDef < MethodDef
7
- def initialize(iseq, cref)
7
+ def initialize(iseq, cref, outer_ep)
8
8
  @iseq = iseq
9
9
  raise if iseq.nil?
10
10
  @cref = cref
11
+ @outer_ep = outer_ep
11
12
  end
12
13
 
13
14
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
@@ -25,7 +26,7 @@ module TypeProf
25
26
  end
26
27
 
27
28
  nctx = Context.new(@iseq, @cref, mid)
28
- callee_ep = ExecutionPoint.new(nctx, 0, nil)
29
+ callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
29
30
  nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
30
31
  alloc_site = AllocationSite.new(callee_ep)
31
32
  locals.each_with_index do |ty, i|
@@ -44,6 +45,14 @@ module TypeProf
44
45
  end
45
46
 
46
47
  def do_check_send(msig, recv, mid, ep, scratch)
48
+ klass, singleton = recv.method_dispatch_info
49
+ cur_subst = {}
50
+ direct_method = true
51
+ scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
52
+ direct_method &&= direct
53
+ cur_subst = Type.merge_substitution(cur_subst, subst)
54
+ end
55
+
47
56
  lead_num = @iseq.fargs_format[:lead_num] || 0
48
57
  post_num = @iseq.fargs_format[:post_num] || 0
49
58
  rest_start = @iseq.fargs_format[:rest_start]
@@ -67,7 +76,8 @@ module TypeProf
67
76
  post_start = @iseq.fargs_format[:post_start]
68
77
  rest_start = @iseq.fargs_format[:rest_start]
69
78
  kw_start = @iseq.fargs_format[:kwbits]
70
- kw_start -= @iseq.fargs_format[:keyword].size if kw_start
79
+ keyword = @iseq.fargs_format[:keyword]
80
+ kw_start -= keyword.size if kw_start
71
81
  kw_rest = @iseq.fargs_format[:kwrest]
72
82
  block_start = @iseq.fargs_format[:block_start]
73
83
 
@@ -83,12 +93,14 @@ module TypeProf
83
93
  msig.lead_tys.each_with_index do |ty, i|
84
94
  alloc_site2 = alloc_site.add_id(idx += 1)
85
95
  # nenv is top-level, so it is okay to call Type#localize directly
96
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
86
97
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
87
98
  nenv = nenv.local_update(i, ty)
88
99
  end
89
100
  if msig.opt_tys
90
101
  msig.opt_tys.each_with_index do |ty, i|
91
102
  alloc_site2 = alloc_site.add_id(idx += 1)
103
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
92
104
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
93
105
  nenv = nenv.local_update(lead_num + i, ty)
94
106
  end
@@ -96,19 +108,27 @@ module TypeProf
96
108
  if msig.rest_ty
97
109
  alloc_site2 = alloc_site.add_id(idx += 1)
98
110
  ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
111
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
99
112
  nenv, rest_ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
100
113
  nenv = nenv.local_update(rest_start, rest_ty)
101
114
  end
102
115
  if msig.post_tys
103
116
  msig.post_tys.each_with_index do |ty, i|
104
117
  alloc_site2 = alloc_site.add_id(idx += 1)
118
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
105
119
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
106
120
  nenv = nenv.local_update(post_start + i, ty)
107
121
  end
108
122
  end
109
123
  if msig.kw_tys
110
- msig.kw_tys.each_with_index do |(_, key, ty), i|
124
+ msig.kw_tys.each do |_, key, ty|
125
+ i = keyword.index(key)
126
+ unless i
127
+ # warn
128
+ next
129
+ end
111
130
  alloc_site2 = alloc_site.add_id(key)
131
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
112
132
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
113
133
  nenv = nenv.local_update(kw_start + i, ty)
114
134
  end
@@ -116,6 +136,7 @@ module TypeProf
116
136
  if msig.kw_rest_ty
117
137
  ty = msig.kw_rest_ty
118
138
  alloc_site2 = alloc_site.add_id(:**)
139
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
119
140
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
120
141
  nenv = nenv.local_update(kw_rest, ty)
121
142
  end
@@ -171,30 +192,11 @@ module TypeProf
171
192
  def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
172
193
  recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
173
194
 
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
195
  klass, singleton = recv_orig.method_dispatch_info
196
196
  cur_subst = {}
197
- scratch.generate_substitution(klass, singleton, mid, self, tmp_subst) do |subst|
197
+ direct_method = true
198
+ scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
199
+ direct_method &&= direct
198
200
  cur_subst = Type.merge_substitution(cur_subst, subst)
199
201
  end
200
202
 
@@ -206,45 +208,15 @@ module TypeProf
206
208
  # XXX: support self type in msig
207
209
  subst = aargs.consistent_with_method_signature?(msig)
208
210
  next unless subst
209
- case
210
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
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
213
- tyvars.each_with_index do |tyvar, idx|
214
- ty = subst[tyvar]
215
- if ty
216
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
217
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
218
- elems.update(idx, ty)
219
- end
220
- end
221
- end
222
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
223
- tyvar_elem = Type::Var.new(:Elem)
224
- if subst[tyvar_elem]
225
- ty = subst[tyvar_elem]
226
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
227
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
228
- elems.update(nil, ty)
229
- end
230
- end
231
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
232
- tyvar_k = Type::Var.new(:K)
233
- tyvar_v = Type::Var.new(:V)
234
- if subst[tyvar_k] && subst[tyvar_v]
235
- k_ty = subst[tyvar_k]
236
- v_ty = subst[tyvar_v]
237
- alloc_site = AllocationSite.new(caller_ep)
238
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
239
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
240
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
241
- elems.update(k_ty, v_ty)
242
- end
243
- end
211
+
212
+ if direct_method && recv_orig.is_a?(Type::Local)
213
+ ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch)
244
214
  end
215
+
245
216
  subst = Type.merge_substitution(subst, cur_subst)
246
217
  # need to check self tyvar?
247
218
  subst[Type::Var.new(:self)] = recv
219
+
248
220
  found = true
249
221
  if aargs.blk_ty.is_a?(Type::Proc)
250
222
  #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
@@ -255,88 +227,30 @@ module TypeProf
255
227
  dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
256
228
  if msig.blk_ty.is_a?(Type::Proc)
257
229
  scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
258
- nfargs = msig.blk_ty.block_body.msig
230
+ bsig = msig.blk_ty.block_body.msig
259
231
  alloc_site = AllocationSite.new(caller_ep).add_id(self)
260
- nlead_tys = (nfargs.lead_tys + nfargs.opt_tys).map.with_index do |ty, i|
261
- if recv.is_a?(Type::Array)
262
- tyvar_elem = Type::Var.new(:Elem)
263
- ty = ty.substitute(subst.merge({ tyvar_elem => recv.elems.squash_or_any }), Config.options[:type_depth_limit])
264
- else
265
- ty = ty.substitute(subst, Config.options[:type_depth_limit])
266
- end
267
- ty = ty.remove_type_vars
268
- alloc_site2 = alloc_site.add_id(i)
269
- dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site2)
232
+ nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i|
233
+ ty = ty.substitute(subst, Config.options[:type_depth_limit]).remove_type_vars
234
+ dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i))
270
235
  ty
271
236
  end
272
- 0.upto(nfargs.opt_tys.size) do |n|
273
- naargs = ActualArguments.new(nlead_tys[0, nfargs.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
237
+ 0.upto(bsig.opt_tys.size) do |n|
238
+ naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
274
239
  scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
275
240
  subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
276
241
  if subst2
277
242
  subst2 = Type.merge_substitution(subst, subst2)
278
- case
279
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
280
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
281
- tyvars.each_with_index do |tyvar, idx|
282
- ty = subst2[tyvar]
283
- if ty
284
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
285
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
286
- elems.update(idx, ty)
287
- end
288
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
289
- end
290
- end
291
- tyvars.zip(recv.elems.elems) do |tyvar, elem|
292
- if subst2[tyvar]
293
- subst2[tyvar] = subst2[tyvar].union(elem)
294
- else
295
- subst2[tyvar] = elem
296
- end
297
- end
298
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
299
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
300
- tyvar_elem = Type::Var.new(:Elem)
301
- if subst2[tyvar_elem]
302
- ty = subst2[tyvar_elem]
303
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
304
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
305
- elems.update(nil, ty)
306
- end
307
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
308
- end
309
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
310
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
311
- tyvar_k = Type::Var.new(:K)
312
- tyvar_v = Type::Var.new(:V)
313
- k_ty0, v_ty0 = recv.elems.squash
314
- if subst2[tyvar_k] && subst2[tyvar_v]
315
- k_ty = subst2[tyvar_k]
316
- v_ty = subst2[tyvar_v]
317
- k_ty0 = k_ty0.union(k_ty)
318
- v_ty0 = v_ty0.union(v_ty)
319
- alloc_site = AllocationSite.new(caller_ep)
320
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
321
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
322
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
323
- elems.update(k_ty, v_ty)
324
- end
325
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
326
- end
327
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
328
- else
329
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
243
+ if direct_method && recv_orig.is_a?(Type::Local)
244
+ ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch)
245
+ scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
330
246
  end
247
+ ret_ty2 = ret_ty.substitute(subst2, Config.options[:type_depth_limit]).remove_type_vars
331
248
  else
332
- # raise "???"
333
- # XXX: need warning
334
- ret_ty = Type.any
249
+ ret_ty2 = Type.any
335
250
  end
336
- ret_ty = ret_ty.remove_type_vars
337
251
  # XXX: check the return type from the block
338
252
  # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
339
- scratch.add_return_value!(dummy_ctx, ret_ty)
253
+ scratch.add_return_value!(dummy_ctx, ret_ty2)
340
254
  end
341
255
  # scratch.add_return_value!(dummy_ctx, ret_ty) ?
342
256
  # This makes `def foo; 1.times { return "str" }; end` return Integer|String
@@ -149,6 +149,10 @@ module TypeProf
149
149
  raise "cannot substitute abstract type: #{ self.class }"
150
150
  end
151
151
 
152
+ def generate_substitution
153
+ {}
154
+ end
155
+
152
156
  DummySubstitution = Object.new
153
157
  def DummySubstitution.[](_)
154
158
  Type.any
@@ -203,11 +207,12 @@ module TypeProf
203
207
  local = nil
204
208
  tys.each do |ty|
205
209
  raise ty.inspect unless ty.is_a?(Type)
206
- local = true if ty.is_a?(LocalArray) || ty.is_a?(LocalHash)
210
+ local = true if ty.is_a?(Local)
207
211
  end
208
212
  raise if local && elems
209
213
 
210
214
  @elems = elems
215
+ raise elems.inspect if elems && !elems.is_a?(::Hash)
211
216
  end
212
217
 
213
218
  def each_free_type_variable(&blk)
@@ -285,7 +290,7 @@ module TypeProf
285
290
  types.delete(Type::Instance.new(Type::Builtin[:true]))
286
291
  bool = true
287
292
  end
288
- types.delete(Type.any) unless Config.options[:pedantic_output]
293
+ types.delete(Type.any) unless Config.options[:show_untyped]
289
294
  proc_tys, types = types.partition {|ty| ty.is_a?(Proc) }
290
295
  types = types.map {|ty| ty.screen_name(scratch) }
291
296
  types << scratch.show_proc_signature(proc_tys) unless proc_tys.empty?
@@ -817,6 +822,7 @@ module TypeProf
817
822
  @opt_tys = opt_tys
818
823
  @rest_ty = rest_ty
819
824
  @post_tys = post_tys
825
+ raise unless post_tys
820
826
  @kw_tys = kw_tys
821
827
  kw_tys.each {|a| raise if a.size != 3 } if kw_tys
822
828
  @kw_rest_ty = kw_rest_ty