typeprof 0.6.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -5
- data/doc/doc.ja.md +3 -4
- data/doc/doc.md +3 -4
- data/lib/typeprof/analyzer.rb +214 -133
- data/lib/typeprof/arguments.rb +14 -6
- data/lib/typeprof/block.rb +6 -2
- data/lib/typeprof/builtin.rb +223 -71
- data/lib/typeprof/cli.rb +33 -34
- data/lib/typeprof/config.rb +6 -4
- data/lib/typeprof/container-type.rb +154 -99
- data/lib/typeprof/export.rb +23 -17
- data/lib/typeprof/import.rb +49 -42
- data/lib/typeprof/iseq.rb +23 -7
- data/lib/typeprof/method.rb +63 -147
- data/lib/typeprof/type.rb +63 -7
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +5 -4
- data/smoke/alias2.rb +4 -4
- data/smoke/any1.rb +2 -1
- data/smoke/any2.rb +3 -2
- data/smoke/arguments.rb +3 -2
- data/smoke/arguments2.rb +11 -10
- data/smoke/array-each.rb +2 -1
- data/smoke/array-each2.rb +2 -1
- data/smoke/array-each3.rb +2 -1
- data/smoke/array-ltlt.rb +2 -1
- data/smoke/array-ltlt2.rb +2 -1
- data/smoke/array-map.rb +2 -1
- data/smoke/array-map2.rb +2 -1
- data/smoke/array-map3.rb +4 -3
- data/smoke/array-mul.rb +3 -2
- data/smoke/array-plus1.rb +2 -1
- data/smoke/array-plus2.rb +2 -2
- data/smoke/array-pop.rb +2 -1
- data/smoke/array-range-aref.rb +71 -0
- data/smoke/array-replace.rb +2 -1
- data/smoke/array-s-aref.rb +2 -1
- data/smoke/array1.rb +6 -5
- data/smoke/array10.rb +2 -1
- data/smoke/array11.rb +2 -1
- data/smoke/array12.rb +4 -3
- data/smoke/array13.rb +5 -4
- data/smoke/array14.rb +2 -1
- data/smoke/array15.rb +16 -0
- data/smoke/array2.rb +4 -3
- data/smoke/array3.rb +4 -4
- data/smoke/array4.rb +2 -1
- data/smoke/array5.rb +2 -1
- data/smoke/array6.rb +3 -2
- data/smoke/array7.rb +2 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +2 -1
- data/smoke/attr-module.rb +26 -0
- data/smoke/attr.rb +5 -5
- data/smoke/autoload.rb +14 -0
- data/smoke/backtrace.rb +4 -3
- data/smoke/block-ambiguous.rb +9 -8
- data/smoke/block-args1-rest.rb +12 -11
- data/smoke/block-args1.rb +11 -10
- data/smoke/block-args2-rest.rb +12 -11
- data/smoke/block-args2.rb +11 -10
- data/smoke/block-args3-rest.rb +14 -13
- data/smoke/block-args3.rb +13 -12
- data/smoke/block-blockarg.rb +5 -4
- data/smoke/block-kwarg.rb +11 -10
- data/smoke/block1.rb +2 -1
- data/smoke/block10.rb +2 -1
- data/smoke/block11.rb +6 -5
- data/smoke/block12.rb +3 -2
- data/smoke/block14.rb +3 -2
- data/smoke/block2.rb +2 -1
- data/smoke/block3.rb +3 -3
- data/smoke/block4.rb +3 -2
- data/smoke/block5.rb +3 -2
- data/smoke/block6.rb +3 -2
- data/smoke/block7.rb +2 -1
- data/smoke/block8.rb +4 -3
- data/smoke/block9.rb +2 -1
- data/smoke/blown.rb +2 -1
- data/smoke/break1.rb +3 -2
- data/smoke/break2.rb +2 -1
- data/smoke/break3.rb +13 -0
- data/smoke/case.rb +2 -1
- data/smoke/case2.rb +2 -1
- data/smoke/case3.rb +17 -0
- data/smoke/class-hierarchy.rb +5 -5
- data/smoke/class-hierarchy2.rb +3 -3
- data/smoke/class-new.rb +15 -0
- data/smoke/class_instance_var.rb +1 -1
- data/smoke/class_method.rb +2 -2
- data/smoke/class_method2.rb +2 -2
- data/smoke/class_method3.rb +4 -2
- data/smoke/constant1.rb +6 -6
- data/smoke/constant2.rb +5 -4
- data/smoke/constant3.rb +2 -1
- data/smoke/constant4.rb +2 -1
- data/smoke/context-sensitive1.rb +2 -1
- data/smoke/cvar.rb +6 -5
- data/smoke/cvar2.rb +2 -2
- data/smoke/define_method.rb +16 -0
- data/smoke/define_method2.rb +18 -0
- data/smoke/define_method3.rb +13 -0
- data/smoke/define_method3.rbs +3 -0
- data/smoke/define_method4.rb +15 -0
- data/smoke/define_method4.rbs +3 -0
- data/smoke/define_method5.rb +12 -0
- data/smoke/demo.rb +7 -6
- data/smoke/demo1.rb +2 -1
- data/smoke/demo10.rb +3 -2
- data/smoke/demo11.rb +2 -1
- data/smoke/demo2.rb +2 -1
- data/smoke/demo3.rb +2 -1
- data/smoke/demo4.rb +3 -3
- data/smoke/demo5.rb +1 -1
- data/smoke/demo6.rb +3 -3
- data/smoke/demo7.rb +2 -1
- data/smoke/demo8.rb +3 -2
- data/smoke/demo9.rb +3 -2
- data/smoke/dummy-execution1.rb +3 -2
- data/smoke/dummy-execution2.rb +2 -2
- data/smoke/dummy_element.rb +14 -0
- data/smoke/ensure1.rb +3 -2
- data/smoke/enumerator.rb +3 -2
- data/smoke/expandarray1.rb +2 -1
- data/smoke/expandarray2.rb +2 -1
- data/smoke/fib.rb +2 -2
- data/smoke/flip-flop.rb +28 -0
- data/smoke/flow1.rb +2 -1
- data/smoke/flow2.rb +2 -1
- data/smoke/flow3.rb +2 -1
- data/smoke/flow5.rb +2 -1
- data/smoke/flow6.rb +2 -1
- data/smoke/flow7.rb +2 -1
- data/smoke/flow8.rb +2 -1
- data/smoke/flow9.rb +12 -0
- data/smoke/freeze.rb +2 -1
- data/smoke/function.rb +3 -2
- data/smoke/gvar.rb +3 -2
- data/smoke/gvar2.rb +3 -2
- data/smoke/hash-bot.rb +12 -0
- data/smoke/hash-fetch.rb +4 -3
- data/smoke/hash-merge-bang.rb +2 -1
- data/smoke/hash1.rb +3 -2
- data/smoke/hash2.rb +2 -1
- data/smoke/hash3.rb +2 -1
- data/smoke/hash4.rb +2 -1
- data/smoke/hash5.rb +1 -1
- data/smoke/inheritance.rb +4 -4
- data/smoke/inheritance2.rb +2 -2
- data/smoke/initialize.rb +6 -5
- data/smoke/instance_eval.rb +2 -2
- data/smoke/instance_eval2.rb +10 -0
- data/smoke/instance_eval3.rb +25 -0
- data/smoke/int_times.rb +2 -1
- data/smoke/integer.rb +2 -1
- data/smoke/ivar.rb +5 -4
- data/smoke/ivar2.rb +4 -4
- data/smoke/ivar3.rb +2 -2
- data/smoke/ivar4.rb +20 -0
- data/smoke/kernel-class.rb +2 -1
- data/smoke/keyword1.rb +2 -1
- data/smoke/keyword2.rb +2 -1
- data/smoke/keyword3.rb +2 -1
- data/smoke/keyword4.rb +2 -1
- data/smoke/keyword5.rb +2 -1
- data/smoke/kwrest.rb +12 -0
- data/smoke/kwrest.rbs +3 -0
- data/smoke/kwsplat1.rb +5 -4
- data/smoke/kwsplat2.rb +2 -1
- data/smoke/lit-complex.rb +10 -0
- data/smoke/lit-encoding.rb +10 -0
- data/smoke/manual-rbs.rb +4 -3
- data/smoke/manual-rbs2.rb +2 -1
- data/smoke/manual-rbs3.rb +2 -2
- data/smoke/masgn1.rb +2 -1
- data/smoke/masgn2.rb +3 -2
- data/smoke/masgn3.rb +2 -1
- data/smoke/method_in_branch.rb +3 -2
- data/smoke/method_missing.rb +28 -0
- data/smoke/module1.rb +2 -2
- data/smoke/module2.rb +1 -1
- data/smoke/module3.rb +2 -2
- data/smoke/module4.rb +2 -2
- data/smoke/module5.rb +17 -0
- data/smoke/module6.rb +40 -0
- data/smoke/module_function1.rb +3 -3
- data/smoke/module_function2.rb +3 -3
- data/smoke/multiple-include.rb +1 -1
- data/smoke/multiple-superclass.rb +1 -1
- data/smoke/next1.rb +3 -2
- data/smoke/next2.rb +2 -1
- data/smoke/object-send1.rb +4 -3
- data/smoke/object-send2.rb +10 -0
- data/smoke/object-send3.rb +18 -0
- data/smoke/once.rb +2 -1
- data/smoke/optional1.rb +2 -1
- data/smoke/optional2.rb +2 -1
- data/smoke/optional3.rb +2 -1
- data/smoke/parameterizedd-self.rb +3 -2
- data/smoke/parameterizedd-self2.rb +1 -1
- data/smoke/pathname1.rb +2 -1
- data/smoke/pathname2.rb +2 -1
- data/smoke/pattern-match1.rb +2 -1
- data/smoke/pattern-match2.rb +2 -1
- data/smoke/printf.rb +2 -2
- data/smoke/proc.rb +3 -2
- data/smoke/proc2.rb +2 -1
- data/smoke/proc3.rb +2 -1
- data/smoke/proc4.rb +2 -1
- data/smoke/proc5.rb +19 -0
- data/smoke/public.rb +34 -0
- data/smoke/range.rb +2 -1
- data/smoke/rbs-alias.rb +2 -1
- data/smoke/rbs-attr.rb +6 -5
- data/smoke/rbs-attr2.rb +11 -0
- data/smoke/rbs-attr2.rbs +3 -0
- data/smoke/rbs-extend.rb +2 -1
- data/smoke/rbs-interface.rb +5 -4
- data/smoke/rbs-module.rb +26 -0
- data/smoke/rbs-module.rbs +4 -0
- data/smoke/rbs-opt-and-rest.rb +10 -0
- data/smoke/rbs-opt-and-rest.rbs +3 -0
- data/smoke/rbs-proc1.rb +2 -1
- data/smoke/rbs-proc2.rb +3 -2
- data/smoke/rbs-proc3.rb +2 -1
- data/smoke/rbs-record.rb +3 -2
- data/smoke/rbs-tyvar.rb +3 -2
- data/smoke/rbs-tyvar2.rb +3 -2
- data/smoke/rbs-tyvar3.rb +3 -2
- data/smoke/rbs-tyvar4.rb +3 -3
- data/smoke/rbs-tyvar5.rb +2 -1
- data/smoke/rbs-tyvar6.rb +4 -3
- data/smoke/rbs-tyvar7.rb +12 -0
- data/smoke/rbs-tyvar7.rbs +7 -0
- data/smoke/rbs-vars.rb +7 -8
- data/smoke/redo1.rb +3 -2
- data/smoke/redo2.rb +3 -2
- data/smoke/req-keyword.rb +2 -1
- data/smoke/rescue1.rb +3 -2
- data/smoke/rescue2.rb +3 -2
- data/smoke/rescue3.rb +19 -0
- data/smoke/rescue4.rb +17 -0
- data/smoke/respond_to.rb +2 -1
- data/smoke/rest-farg.rb +2 -1
- data/smoke/rest1.rb +3 -2
- data/smoke/rest2.rb +2 -1
- data/smoke/rest3.rb +7 -6
- data/smoke/rest4.rb +3 -2
- data/smoke/rest5.rb +2 -1
- data/smoke/rest6.rb +2 -1
- data/smoke/retry1.rb +3 -2
- data/smoke/return.rb +2 -1
- data/smoke/singleton_method.rb +1 -1
- data/smoke/step.rb +4 -3
- data/smoke/string-split.rb +2 -1
- data/smoke/struct-keyword_init.rb +20 -0
- data/smoke/struct.rb +1 -1
- data/smoke/struct2.rb +5 -4
- data/smoke/struct3.rb +2 -2
- data/smoke/struct4.rb +7 -0
- data/smoke/struct5.rb +16 -0
- data/smoke/struct6.rb +15 -0
- data/smoke/struct7.rb +17 -0
- data/smoke/stub-keyword.rb +10 -0
- data/smoke/super1.rb +5 -4
- data/smoke/super2.rb +1 -1
- data/smoke/super3.rb +3 -3
- data/smoke/super4.rb +5 -5
- data/smoke/super5.rb +4 -4
- data/smoke/svar1.rb +2 -1
- data/smoke/symbol-proc-attr.rb +22 -0
- data/smoke/symbol-proc-attr2.rb +15 -0
- data/smoke/symbol-proc-bot.rb +13 -0
- data/smoke/symbol-proc.rb +4 -3
- data/smoke/tap1.rb +3 -2
- data/smoke/toplevel.rb +2 -1
- data/smoke/two-map.rb +3 -2
- data/smoke/type_var.rb +2 -1
- data/smoke/typed_method.rb +2 -1
- data/smoke/uninitialize-var.rb +2 -1
- data/smoke/union-recv.rb +2 -2
- data/smoke/user-demo.rb +3 -3
- data/smoke/wrong-extend.rb +2 -2
- data/smoke/wrong-include.rb +2 -2
- data/smoke/wrong-include2.rb +17 -0
- data/typeprof.gemspec +1 -1
- metadata +56 -5
- data/tools/stackprof-wrapper.rb +0 -10
data/lib/typeprof/export.rb
CHANGED
@@ -72,7 +72,7 @@ module TypeProf
|
|
72
72
|
gvars.dump.each do |gvar_name, entry|
|
73
73
|
next if entry.type == Type.bot
|
74
74
|
s = entry.rbs_declared ? "#" : ""
|
75
|
-
output.puts s + "#{ gvar_name }
|
75
|
+
output.puts s + "#{ gvar_name }: #{ entry.type.screen_name(scratch) }"
|
76
76
|
end
|
77
77
|
output.puts
|
78
78
|
end
|
@@ -135,11 +135,12 @@ module TypeProf
|
|
135
135
|
method_name = ctx.mid
|
136
136
|
method_name = "self.#{ method_name }" if singleton
|
137
137
|
|
138
|
-
iseq_methods[method_name] ||= []
|
139
|
-
iseq_methods[method_name]
|
138
|
+
iseq_methods[method_name] ||= [true, []]
|
139
|
+
iseq_methods[method_name][0] &&= mdef.pub_meth
|
140
|
+
iseq_methods[method_name][1] << @scratch.show_method_signature(ctx)
|
140
141
|
end
|
141
142
|
when AttrMethodDef
|
142
|
-
next if Config.check_dir_filter(mdef.absolute_path) == :exclude
|
143
|
+
next if !mdef.absolute_path || Config.check_dir_filter(mdef.absolute_path) == :exclude
|
143
144
|
mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
|
144
145
|
method_name = mid
|
145
146
|
method_name = "self.#{ mid }" if singleton
|
@@ -168,12 +169,14 @@ module TypeProf
|
|
168
169
|
next unless var.to_s.start_with?("@")
|
169
170
|
var = "self.#{ var }" if singleton
|
170
171
|
next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
|
171
|
-
|
172
|
+
next if entry.rbs_declared
|
173
|
+
[var, ty.screen_name(@scratch)]
|
172
174
|
end.compact
|
173
175
|
|
174
176
|
cvars = cvars.map do |var, entry|
|
175
177
|
next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
|
176
|
-
|
178
|
+
next if entry.rbs_declared
|
179
|
+
[var, entry.type.screen_name(@scratch)]
|
177
180
|
end.compact
|
178
181
|
|
179
182
|
if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
|
@@ -266,7 +269,7 @@ module TypeProf
|
|
266
269
|
output.puts indent + "#{ class_data.kind } #{ name }#{ superclass }"
|
267
270
|
first = true
|
268
271
|
class_data.consts.each do |name, ty|
|
269
|
-
output.puts indent + " #{ name }
|
272
|
+
output.puts indent + " #{ name }: #{ ty }"
|
270
273
|
first = false
|
271
274
|
end
|
272
275
|
class_data.included_mods.sort.each do |mod|
|
@@ -277,28 +280,31 @@ module TypeProf
|
|
277
280
|
output.puts indent + " extend #{ mod }"
|
278
281
|
first = false
|
279
282
|
end
|
280
|
-
class_data.ivars.each do |var, ty
|
281
|
-
|
282
|
-
output.puts indent + s + "#{ var } : #{ ty }" unless var.start_with?("_")
|
283
|
+
class_data.ivars.each do |var, ty|
|
284
|
+
output.puts indent + " #{ var }: #{ ty }" unless var.start_with?("_")
|
283
285
|
first = false
|
284
286
|
end
|
285
|
-
class_data.cvars.each do |var, ty
|
286
|
-
|
287
|
-
output.puts indent + s + "#{ var } : #{ ty }"
|
287
|
+
class_data.cvars.each do |var, ty|
|
288
|
+
output.puts indent + " #{ var }: #{ ty }"
|
288
289
|
first = false
|
289
290
|
end
|
290
291
|
class_data.attr_methods.each do |(method_name, hidden), (kind, ty)|
|
291
|
-
output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }
|
292
|
+
output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }"
|
292
293
|
first = false
|
293
294
|
end
|
294
295
|
class_data.explicit_methods.each do |method_name, sigs|
|
295
296
|
sigs = sigs.sort.join("\n" + indent + "#" + " " * (method_name.size + 6) + "| ")
|
296
|
-
output.puts indent + "# def #{ method_name }
|
297
|
+
output.puts indent + "# def #{ method_name }: #{ sigs }"
|
297
298
|
first = false
|
298
299
|
end
|
299
|
-
|
300
|
+
prev_pub_meth = true
|
301
|
+
class_data.iseq_methods.each do |method_name, (pub_meth, sigs)|
|
300
302
|
sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 7) + "| ")
|
301
|
-
|
303
|
+
if prev_pub_meth != pub_meth
|
304
|
+
output.puts indent + " #{ pub_meth ? "public" : "private" }"
|
305
|
+
prev_pub_meth = pub_meth
|
306
|
+
end
|
307
|
+
output.puts indent + " def #{ method_name }: #{ sigs }"
|
302
308
|
first = false
|
303
309
|
end
|
304
310
|
show_class_hierarchy(depth + 1, class_data.inner_classes, output, first)
|
data/lib/typeprof/import.rb
CHANGED
@@ -26,6 +26,13 @@ module TypeProf
|
|
26
26
|
def load_library(lib)
|
27
27
|
loader = RBS::EnvironmentLoader.new(core_root: nil)
|
28
28
|
loader.add(library: lib)
|
29
|
+
|
30
|
+
case lib
|
31
|
+
when "yaml"
|
32
|
+
loader.add(library: "pstore")
|
33
|
+
loader.add(library: "dbm")
|
34
|
+
end
|
35
|
+
|
29
36
|
new_decls = loader.load(env: @env).map {|decl,| decl }
|
30
37
|
RBSReader.load_rbs(@env, new_decls)
|
31
38
|
end
|
@@ -112,6 +119,7 @@ module TypeProf
|
|
112
119
|
included_modules = []
|
113
120
|
extended_modules = []
|
114
121
|
methods = {}
|
122
|
+
attr_methods = {}
|
115
123
|
ivars = {}
|
116
124
|
cvars = {}
|
117
125
|
rbs_sources = {}
|
@@ -147,15 +155,15 @@ module TypeProf
|
|
147
155
|
end
|
148
156
|
when RBS::AST::Members::AttrReader
|
149
157
|
ty = conv_type(member.type)
|
150
|
-
|
158
|
+
attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
|
151
159
|
when RBS::AST::Members::AttrWriter
|
152
160
|
ty = conv_type(member.type)
|
153
|
-
|
161
|
+
attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
|
154
162
|
when RBS::AST::Members::AttrAccessor
|
155
163
|
ty = conv_type(member.type)
|
156
|
-
|
157
|
-
methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
|
164
|
+
attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
|
158
165
|
when RBS::AST::Members::Alias
|
166
|
+
# XXX: an alias to attr methods?
|
159
167
|
if member.instance?
|
160
168
|
method_def = methods[[false, member.old_name]]
|
161
169
|
methods[[false, member.new_name]] = method_def if method_def
|
@@ -211,6 +219,7 @@ module TypeProf
|
|
211
219
|
included_modules: included_modules,
|
212
220
|
extended_modules: extended_modules,
|
213
221
|
methods: methods,
|
222
|
+
attr_methods: attr_methods,
|
214
223
|
ivars: ivars,
|
215
224
|
cvars: cvars,
|
216
225
|
rbs_sources: rbs_sources,
|
@@ -237,7 +246,7 @@ module TypeProf
|
|
237
246
|
@all_env.class_decls[name].decls.each do |decl|
|
238
247
|
decl = decl.decl
|
239
248
|
next if decl.is_a?(RBS::AST::Declarations::Module)
|
240
|
-
|
249
|
+
each_reference(decl) {|name| queue << [:visit, name] }
|
241
250
|
end
|
242
251
|
queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
|
243
252
|
end
|
@@ -252,13 +261,20 @@ module TypeProf
|
|
252
261
|
end
|
253
262
|
end
|
254
263
|
|
255
|
-
def
|
264
|
+
def each_reference(decl, &blk)
|
256
265
|
yield decl.name
|
257
|
-
|
266
|
+
if decl.super_class
|
267
|
+
name = decl.super_class.name
|
268
|
+
else
|
269
|
+
name = RBS::BuiltinNames::Object.name
|
270
|
+
end
|
258
271
|
return if decl.name == RBS::BuiltinNames::BasicObject.name
|
259
|
-
return if decl.name ==
|
260
|
-
@all_env.class_decls[
|
261
|
-
|
272
|
+
return if decl.name == name
|
273
|
+
decls = @all_env.class_decls[name]
|
274
|
+
if decls
|
275
|
+
decls.decls.each do |decl|
|
276
|
+
each_reference(decl.decl, &blk)
|
277
|
+
end
|
262
278
|
end
|
263
279
|
end
|
264
280
|
|
@@ -297,7 +313,7 @@ module TypeProf
|
|
297
313
|
opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
298
314
|
req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
|
299
315
|
rest_kw_ty = func.rest_keywords
|
300
|
-
|
316
|
+
rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
|
301
317
|
|
302
318
|
ret_ty = conv_type(func.return_type)
|
303
319
|
|
@@ -314,32 +330,12 @@ module TypeProf
|
|
314
330
|
}
|
315
331
|
end
|
316
332
|
|
317
|
-
def
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
req_kw_tys: {},
|
324
|
-
opt_kw_tys: {},
|
325
|
-
rest_kw_ty: nil,
|
326
|
-
blk: nil,
|
327
|
-
ret_ty: ty,
|
328
|
-
}]
|
329
|
-
end
|
330
|
-
|
331
|
-
def attr_writer_def(ty)
|
332
|
-
[{
|
333
|
-
type_params: [],
|
334
|
-
lead_tys: [ty],
|
335
|
-
opt_tys: [],
|
336
|
-
rest_ty: nil,
|
337
|
-
req_kw_tys: {},
|
338
|
-
opt_kw_tys: {},
|
339
|
-
rest_kw_ty: nil,
|
340
|
-
blk: nil,
|
341
|
-
ret_ty: ty,
|
342
|
-
}]
|
333
|
+
def attr_method_def(kind, name, ty)
|
334
|
+
{
|
335
|
+
kind: kind,
|
336
|
+
ivar: name,
|
337
|
+
ty: ty,
|
338
|
+
}
|
343
339
|
end
|
344
340
|
|
345
341
|
def conv_block(rbs_block)
|
@@ -452,6 +448,8 @@ module TypeProf
|
|
452
448
|
json = scratch.rbs_reader.load_library(feature)
|
453
449
|
rescue RBS::EnvironmentLoader::UnknownLibraryError
|
454
450
|
return nil
|
451
|
+
rescue RBS::DuplicatedDeclarationError
|
452
|
+
return true
|
455
453
|
end
|
456
454
|
# need cache?
|
457
455
|
Import.new(scratch, json).import
|
@@ -483,8 +481,7 @@ module TypeProf
|
|
483
481
|
|
484
482
|
klass = @scratch.get_constant(base_klass, name)
|
485
483
|
if klass.is_a?(Type::Any)
|
486
|
-
|
487
|
-
klass = @scratch.new_class(base_klass, name, type_params, superclass, superclass_type_args, nil)
|
484
|
+
klass = @scratch.new_class(base_klass, name, type_params, superclass, nil)
|
488
485
|
|
489
486
|
# There builtin classes are needed to interpret RBS declarations
|
490
487
|
case classpath
|
@@ -500,13 +497,15 @@ module TypeProf
|
|
500
497
|
end
|
501
498
|
end
|
502
499
|
|
503
|
-
[klass, members]
|
500
|
+
[klass, superclass_type_args, members]
|
504
501
|
end
|
505
502
|
|
506
|
-
classes.each do |klass, members|
|
503
|
+
classes.each do |klass, superclass_type_args, members|
|
504
|
+
@scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
|
507
505
|
included_modules = members[:included_modules]
|
508
506
|
extended_modules = members[:extended_modules]
|
509
507
|
methods = members[:methods]
|
508
|
+
attr_methods = members[:attr_methods]
|
510
509
|
ivars = members[:ivars]
|
511
510
|
cvars = members[:cvars]
|
512
511
|
rbs_sources = members[:rbs_sources]
|
@@ -527,6 +526,14 @@ module TypeProf
|
|
527
526
|
@scratch.add_method(klass, method_name, singleton, mdef)
|
528
527
|
end
|
529
528
|
|
529
|
+
attr_methods.each do |(singleton, method_name), mdef|
|
530
|
+
kind = mdef[:kind]
|
531
|
+
ivar = mdef[:ivar]
|
532
|
+
ty = conv_type(mdef[:ty]).remove_type_vars
|
533
|
+
@scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
|
534
|
+
@scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
|
535
|
+
end
|
536
|
+
|
530
537
|
ivars.each do |ivar_name, ty|
|
531
538
|
ty = conv_type(ty).remove_type_vars
|
532
539
|
@scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
|
@@ -593,7 +600,7 @@ module TypeProf
|
|
593
600
|
req, lead_tys, opt_tys, ret_ty = blk
|
594
601
|
lead_tys = lead_tys.map {|ty| conv_type(ty) }
|
595
602
|
opt_tys = opt_tys.map {|ty| conv_type(ty) }
|
596
|
-
msig = MethodSignature.new(lead_tys, opt_tys, nil,
|
603
|
+
msig = MethodSignature.new(lead_tys, opt_tys, nil, [], {}, nil, Type.nil)
|
597
604
|
ret_ty = conv_type(ret_ty)
|
598
605
|
ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
|
599
606
|
ret << Type.nil unless req
|
data/lib/typeprof/iseq.rb
CHANGED
@@ -49,10 +49,18 @@ module TypeProf
|
|
49
49
|
insns[i, 0] = [[:_iseq_body_start]]
|
50
50
|
end
|
51
51
|
|
52
|
+
# rescue/ensure clauses need to have a dedicated return addresses
|
53
|
+
# because they requires to be virtually called.
|
54
|
+
# So, this preprocess adds "nop" to make a new insn for their return addresses
|
55
|
+
special_labels = {}
|
56
|
+
catch_table.map do |type, iseq, first, last, cont, stack_depth|
|
57
|
+
special_labels[cont] = true if type == :rescue || type == :ensure
|
58
|
+
end
|
59
|
+
|
52
60
|
@insns = []
|
53
61
|
@linenos = []
|
54
62
|
|
55
|
-
labels = setup_iseq(insns)
|
63
|
+
labels = setup_iseq(insns, special_labels)
|
56
64
|
|
57
65
|
# checkmatch->branch
|
58
66
|
# send->branch
|
@@ -60,7 +68,8 @@ module TypeProf
|
|
60
68
|
@catch_table = []
|
61
69
|
catch_table.map do |type, iseq, first, last, cont, stack_depth|
|
62
70
|
iseq = iseq ? ISeq.new(iseq) : nil
|
63
|
-
|
71
|
+
target = labels[special_labels[cont] ? :"#{ cont }_special" : cont]
|
72
|
+
entry = [type, iseq, target, stack_depth]
|
64
73
|
labels[first].upto(labels[last]) do |i|
|
65
74
|
@catch_table[i] ||= []
|
66
75
|
@catch_table[i] << entry
|
@@ -76,19 +85,26 @@ module TypeProf
|
|
76
85
|
@id <=> other.id
|
77
86
|
end
|
78
87
|
|
79
|
-
def setup_iseq(insns)
|
88
|
+
def setup_iseq(insns, special_labels)
|
80
89
|
i = 0
|
81
90
|
labels = {}
|
91
|
+
ninsns = []
|
82
92
|
insns.each do |e|
|
83
93
|
if e.is_a?(Symbol) && e.to_s.start_with?("label")
|
94
|
+
if special_labels[e]
|
95
|
+
labels[:"#{ e }_special"] = i
|
96
|
+
ninsns << [:nop]
|
97
|
+
i += 1
|
98
|
+
end
|
84
99
|
labels[e] = i
|
85
|
-
|
86
|
-
i += 1
|
100
|
+
else
|
101
|
+
i += 1 if e.is_a?(Array)
|
102
|
+
ninsns << e
|
87
103
|
end
|
88
104
|
end
|
89
105
|
|
90
106
|
lineno = 0
|
91
|
-
|
107
|
+
ninsns.each do |e|
|
92
108
|
case e
|
93
109
|
when Integer # lineno
|
94
110
|
lineno = e
|
@@ -209,7 +225,7 @@ module TypeProf
|
|
209
225
|
end
|
210
226
|
end
|
211
227
|
send_branch_list.each do |i, j|
|
212
|
-
next if (i + 1 .. j).any? {|i| branch_targets[i] }
|
228
|
+
next if (i + 1 .. j + 1).any? {|i| branch_targets[i] }
|
213
229
|
_insn, getlocal_operands = @insns[i]
|
214
230
|
_insn, send_operands = @insns[j]
|
215
231
|
_insn, branch_operands = @insns[j + 1]
|
data/lib/typeprof/method.rb
CHANGED
@@ -4,12 +4,16 @@ module TypeProf
|
|
4
4
|
end
|
5
5
|
|
6
6
|
class ISeqMethodDef < MethodDef
|
7
|
-
def initialize(iseq, cref)
|
7
|
+
def initialize(iseq, cref, outer_ep, pub_meth)
|
8
8
|
@iseq = iseq
|
9
9
|
raise if iseq.nil?
|
10
10
|
@cref = cref
|
11
|
+
@outer_ep = outer_ep
|
12
|
+
@pub_meth = pub_meth
|
11
13
|
end
|
12
14
|
|
15
|
+
attr_accessor :pub_meth
|
16
|
+
|
13
17
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
14
18
|
recv = recv.base_type while recv.respond_to?(:base_type)
|
15
19
|
recv = scratch.globalize_type(recv, caller_env, caller_ep)
|
@@ -25,8 +29,8 @@ module TypeProf
|
|
25
29
|
end
|
26
30
|
|
27
31
|
nctx = Context.new(@iseq, @cref, mid)
|
28
|
-
callee_ep = ExecutionPoint.new(nctx, 0,
|
29
|
-
nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
|
32
|
+
callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
|
33
|
+
nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
|
30
34
|
alloc_site = AllocationSite.new(callee_ep)
|
31
35
|
locals.each_with_index do |ty, i|
|
32
36
|
alloc_site2 = alloc_site.add_id(i)
|
@@ -44,6 +48,14 @@ module TypeProf
|
|
44
48
|
end
|
45
49
|
|
46
50
|
def do_check_send(msig, recv, mid, ep, scratch)
|
51
|
+
klass, singleton = recv.method_dispatch_info
|
52
|
+
cur_subst = {}
|
53
|
+
direct_method = true
|
54
|
+
scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
|
55
|
+
direct_method &&= direct
|
56
|
+
cur_subst = Type.merge_substitution(cur_subst, subst)
|
57
|
+
end
|
58
|
+
|
47
59
|
lead_num = @iseq.fargs_format[:lead_num] || 0
|
48
60
|
post_num = @iseq.fargs_format[:post_num] || 0
|
49
61
|
rest_start = @iseq.fargs_format[:rest_start]
|
@@ -67,63 +79,75 @@ module TypeProf
|
|
67
79
|
post_start = @iseq.fargs_format[:post_start]
|
68
80
|
rest_start = @iseq.fargs_format[:rest_start]
|
69
81
|
kw_start = @iseq.fargs_format[:kwbits]
|
70
|
-
|
82
|
+
keyword = @iseq.fargs_format[:keyword]
|
83
|
+
kw_start -= keyword.size if kw_start
|
71
84
|
kw_rest = @iseq.fargs_format[:kwrest]
|
72
85
|
block_start = @iseq.fargs_format[:block_start]
|
73
86
|
|
74
87
|
# XXX: need to check .rbs msig and .rb fargs
|
75
88
|
|
76
89
|
ctx = Context.new(@iseq, @cref, mid)
|
77
|
-
callee_ep = ExecutionPoint.new(ctx, 0,
|
90
|
+
callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
|
78
91
|
|
79
92
|
locals = [Type.nil] * @iseq.locals.size
|
80
|
-
nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false), locals, [], Utils::HashWrapper.new({}))
|
93
|
+
nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
|
81
94
|
alloc_site = AllocationSite.new(callee_ep)
|
82
95
|
idx = 0
|
83
96
|
msig.lead_tys.each_with_index do |ty, i|
|
84
97
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
85
|
-
|
86
|
-
nenv, ty =
|
98
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
99
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
87
100
|
nenv = nenv.local_update(i, ty)
|
88
101
|
end
|
89
102
|
if msig.opt_tys
|
90
103
|
msig.opt_tys.each_with_index do |ty, i|
|
91
104
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
92
|
-
|
105
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
106
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
93
107
|
nenv = nenv.local_update(lead_num + i, ty)
|
94
108
|
end
|
95
109
|
end
|
96
110
|
if msig.rest_ty
|
97
111
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
98
112
|
ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
|
99
|
-
|
113
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
114
|
+
nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
100
115
|
nenv = nenv.local_update(rest_start, rest_ty)
|
101
116
|
end
|
102
117
|
if msig.post_tys
|
103
118
|
msig.post_tys.each_with_index do |ty, i|
|
104
119
|
alloc_site2 = alloc_site.add_id(idx += 1)
|
105
|
-
|
120
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
121
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
106
122
|
nenv = nenv.local_update(post_start + i, ty)
|
107
123
|
end
|
108
124
|
end
|
109
|
-
if msig.kw_tys
|
110
|
-
msig.kw_tys.
|
125
|
+
if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
|
126
|
+
msig.kw_tys.each do |_, key, ty|
|
127
|
+
i = keyword.index {|callee_key,| callee_key == key }
|
128
|
+
unless i
|
129
|
+
# warn
|
130
|
+
next
|
131
|
+
end
|
111
132
|
alloc_site2 = alloc_site.add_id(key)
|
112
|
-
|
133
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
134
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
113
135
|
nenv = nenv.local_update(kw_start + i, ty)
|
114
136
|
end
|
115
137
|
end
|
116
138
|
if msig.kw_rest_ty
|
117
139
|
ty = msig.kw_rest_ty
|
118
140
|
alloc_site2 = alloc_site.add_id(:**)
|
119
|
-
|
141
|
+
ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
|
142
|
+
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
|
120
143
|
nenv = nenv.local_update(kw_rest, ty)
|
121
144
|
end
|
122
145
|
nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
|
123
146
|
|
124
147
|
opt.each do |start_pc|
|
125
|
-
scratch.merge_env(
|
148
|
+
scratch.merge_env(callee_ep.jump(start_pc), nenv)
|
126
149
|
end
|
150
|
+
scratch.add_executed_iseq(@iseq)
|
127
151
|
|
128
152
|
ctx
|
129
153
|
end
|
@@ -142,8 +166,8 @@ module TypeProf
|
|
142
166
|
case @kind
|
143
167
|
when :reader
|
144
168
|
if aargs.lead_tys.size == 0
|
145
|
-
scratch.
|
146
|
-
ctn[ty, caller_ep,
|
169
|
+
scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
|
170
|
+
ctn[ty, caller_ep, caller_env]
|
147
171
|
end
|
148
172
|
else
|
149
173
|
ctn[Type.any, caller_ep, caller_env]
|
@@ -171,30 +195,11 @@ module TypeProf
|
|
171
195
|
def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
172
196
|
recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
|
173
197
|
|
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
198
|
klass, singleton = recv_orig.method_dispatch_info
|
196
199
|
cur_subst = {}
|
197
|
-
|
200
|
+
direct_method = true
|
201
|
+
scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
|
202
|
+
direct_method &&= direct
|
198
203
|
cur_subst = Type.merge_substitution(cur_subst, subst)
|
199
204
|
end
|
200
205
|
|
@@ -206,45 +211,15 @@ module TypeProf
|
|
206
211
|
# XXX: support self type in msig
|
207
212
|
subst = aargs.consistent_with_method_signature?(msig)
|
208
213
|
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
|
214
|
+
|
215
|
+
if direct_method && recv_orig.is_a?(Type::Local)
|
216
|
+
ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch)
|
244
217
|
end
|
218
|
+
|
245
219
|
subst = Type.merge_substitution(subst, cur_subst)
|
246
220
|
# need to check self tyvar?
|
247
221
|
subst[Type::Var.new(:self)] = recv
|
222
|
+
|
248
223
|
found = true
|
249
224
|
if aargs.blk_ty.is_a?(Type::Proc)
|
250
225
|
#raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
|
@@ -252,91 +227,33 @@ module TypeProf
|
|
252
227
|
dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
|
253
228
|
s_recv = recv
|
254
229
|
s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
|
255
|
-
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
|
230
|
+
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
|
256
231
|
if msig.blk_ty.is_a?(Type::Proc)
|
257
232
|
scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
|
258
|
-
|
233
|
+
bsig = msig.blk_ty.block_body.msig
|
259
234
|
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)
|
235
|
+
nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i|
|
236
|
+
ty = ty.substitute(subst, Config.options[:type_depth_limit]).remove_type_vars
|
237
|
+
dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i))
|
270
238
|
ty
|
271
239
|
end
|
272
|
-
0.upto(
|
273
|
-
naargs = ActualArguments.new(nlead_tys[0,
|
240
|
+
0.upto(bsig.opt_tys.size) do |n|
|
241
|
+
naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
|
274
242
|
scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
|
275
243
|
subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
|
276
244
|
if subst2
|
277
245
|
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])
|
246
|
+
if direct_method && recv_orig.is_a?(Type::Local)
|
247
|
+
ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch)
|
248
|
+
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
330
249
|
end
|
250
|
+
ret_ty2 = ret_ty.substitute(subst2, Config.options[:type_depth_limit]).remove_type_vars
|
331
251
|
else
|
332
|
-
|
333
|
-
# XXX: need warning
|
334
|
-
ret_ty = Type.any
|
252
|
+
ret_ty2 = Type.any
|
335
253
|
end
|
336
|
-
ret_ty = ret_ty.remove_type_vars
|
337
254
|
# XXX: check the return type from the block
|
338
255
|
# sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
|
339
|
-
scratch.add_return_value!(dummy_ctx,
|
256
|
+
scratch.add_return_value!(dummy_ctx, ret_ty2)
|
340
257
|
end
|
341
258
|
# scratch.add_return_value!(dummy_ctx, ret_ty) ?
|
342
259
|
# This makes `def foo; 1.times { return "str" }; end` return Integer|String
|
@@ -374,7 +291,6 @@ module TypeProf
|
|
374
291
|
end
|
375
292
|
|
376
293
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
377
|
-
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
|
378
294
|
@impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
|
379
295
|
end
|
380
296
|
end
|