typeprof 0.6.1 → 0.7.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 +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
|