typeprof 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/doc/doc.ja.md +3 -4
- data/doc/doc.md +3 -4
- data/lib/typeprof/analyzer.rb +95 -80
- data/lib/typeprof/arguments.rb +12 -6
- data/lib/typeprof/builtin.rb +75 -20
- data/lib/typeprof/cli.rb +33 -34
- data/lib/typeprof/config.rb +4 -2
- data/lib/typeprof/container-type.rb +153 -99
- data/lib/typeprof/export.rb +9 -9
- data/lib/typeprof/import.rb +23 -32
- data/lib/typeprof/method.rb +45 -131
- data/lib/typeprof/type.rb +8 -2
- data/lib/typeprof/version.rb +1 -1
- data/smoke/array-each3.rb +1 -1
- data/smoke/array-range-aref.rb +70 -0
- data/smoke/autoload.rb +13 -0
- data/smoke/define_method.rb +16 -0
- data/smoke/define_method2.rb +18 -0
- data/smoke/kwrest.rb +12 -0
- data/smoke/kwrest.rbs +3 -0
- data/smoke/method_missing.rb +28 -0
- data/smoke/rbs-attr.rb +2 -2
- data/smoke/rbs-attr2.rb +11 -0
- data/smoke/rbs-attr2.rbs +3 -0
- data/smoke/rbs-tyvar7.rb +11 -0
- data/smoke/rbs-tyvar7.rbs +7 -0
- data/smoke/rbs-vars.rb +0 -2
- metadata +13 -2
data/lib/typeprof/export.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
281
|
-
|
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
|
286
|
-
|
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)|
|
data/lib/typeprof/import.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
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,
|
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
|
data/lib/typeprof/method.rb
CHANGED
@@ -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,
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
210
|
-
|
211
|
-
|
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
|
-
|
230
|
+
bsig = msig.blk_ty.block_body.msig
|
259
231
|
alloc_site = AllocationSite.new(caller_ep).add_id(self)
|
260
|
-
nlead_tys = (
|
261
|
-
|
262
|
-
|
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(
|
273
|
-
naargs = ActualArguments.new(nlead_tys[0,
|
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
|
-
|
279
|
-
|
280
|
-
|
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
|
-
|
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,
|
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
|
data/lib/typeprof/type.rb
CHANGED
@@ -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?(
|
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[:
|
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
|