typeprof 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +1 -2
- data/Gemfile.lock +1 -1
- data/README.md +6 -0
- data/lib/typeprof/analyzer.rb +67 -28
- data/lib/typeprof/arguments.rb +27 -19
- data/lib/typeprof/block.rb +5 -2
- data/lib/typeprof/builtin.rb +8 -2
- data/lib/typeprof/container-type.rb +104 -97
- data/lib/typeprof/import.rb +16 -8
- data/lib/typeprof/method.rb +70 -12
- data/lib/typeprof/type.rb +103 -88
- data/lib/typeprof/version.rb +1 -1
- data/smoke/arguments2.rb +1 -1
- data/smoke/block-kwarg.rb +1 -1
- data/smoke/block10.rb +1 -1
- data/smoke/hash-fetch.rb +3 -3
- data/smoke/hash-merge-bang.rb +11 -0
- data/smoke/hash1.rb +1 -1
- data/smoke/hash3.rb +1 -1
- data/smoke/hash4.rb +1 -1
- data/smoke/ivar2.rb +1 -1
- data/smoke/keyword4.rb +1 -1
- data/smoke/kwsplat1.rb +1 -1
- data/smoke/kwsplat2.rb +1 -1
- data/smoke/pattern-match1.rb +23 -0
- data/smoke/pattern-match2.rb +15 -0
- data/smoke/rbs-tyvar3.rb +11 -19
- data/smoke/rbs-tyvar3.rbs +4 -3
- data/smoke/rbs-tyvar4.rb +36 -0
- data/smoke/rbs-tyvar5.rb +12 -0
- data/smoke/rbs-tyvar5.rbs +8 -0
- data/smoke/uninitialize-var.rb +12 -0
- metadata +9 -2
data/lib/typeprof/import.rb
CHANGED
@@ -210,7 +210,7 @@ module TypeProf
|
|
210
210
|
# * superclasses and modules appear earlier than their subclasses (Object is earlier than String)
|
211
211
|
# * namespace module appers earlier than its children (Process is earlier than Process::Status)
|
212
212
|
visited = {}
|
213
|
-
queue = @cur_env.class_decls.keys.map {|name| [:visit, name] }
|
213
|
+
queue = @cur_env.class_decls.keys.map {|name| [:visit, name] }.reverse
|
214
214
|
until queue.empty?
|
215
215
|
event, name = queue.pop
|
216
216
|
case event
|
@@ -365,10 +365,15 @@ module TypeProf
|
|
365
365
|
raise if ty.args.size != 2
|
366
366
|
[:array, [:Enumerator], [], conv_type(ty.args.first)]
|
367
367
|
else
|
368
|
-
|
368
|
+
if ty.args.empty?
|
369
|
+
[:instance, klass]
|
370
|
+
else
|
371
|
+
[:cell, [:instance, klass], ty.args.map {|ty| conv_type(ty) }]
|
372
|
+
end
|
369
373
|
end
|
370
374
|
when RBS::Types::Bases::Bool then [:bool]
|
371
375
|
when RBS::Types::Bases::Any then [:any]
|
376
|
+
when RBS::Types::Bases::Top then [:any]
|
372
377
|
when RBS::Types::Bases::Void then [:void]
|
373
378
|
when RBS::Types::Bases::Self then [:self]
|
374
379
|
when RBS::Types::Bases::Nil then [:nil]
|
@@ -499,24 +504,25 @@ module TypeProf
|
|
499
504
|
end
|
500
505
|
|
501
506
|
ivars.each do |ivar_name, ty|
|
502
|
-
ty = conv_type(ty)
|
507
|
+
ty = conv_type(ty).remove_type_vars
|
503
508
|
@scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
|
504
509
|
end
|
505
510
|
|
506
511
|
cvars.each do |ivar_name, ty|
|
507
|
-
ty = conv_type(ty)
|
512
|
+
ty = conv_type(ty).remove_type_vars
|
508
513
|
@scratch.add_cvar_write!(klass, ivar_name, ty, nil)
|
509
514
|
end
|
510
515
|
end
|
511
516
|
|
512
517
|
@json[:constants].each do |classpath, value|
|
513
518
|
base_klass = path_to_klass(classpath[0..-2])
|
514
|
-
value = conv_type(value)
|
519
|
+
value = conv_type(value).remove_type_vars
|
515
520
|
@scratch.add_constant(base_klass, classpath[-1], value, nil)
|
516
521
|
end
|
517
522
|
|
518
|
-
@json[:globals].each do |name,
|
519
|
-
|
523
|
+
@json[:globals].each do |name, ty|
|
524
|
+
ty = conv_type(ty).remove_type_vars
|
525
|
+
@scratch.add_gvar_write!(name, ty, nil)
|
520
526
|
end
|
521
527
|
|
522
528
|
true
|
@@ -574,6 +580,8 @@ module TypeProf
|
|
574
580
|
case ty.first
|
575
581
|
when :class then path_to_klass(ty[1])
|
576
582
|
when :instance then Type::Instance.new(path_to_klass(ty[1]))
|
583
|
+
when :cell
|
584
|
+
Type::Cell.new(Type::Cell::Elements.new(ty[2].map {|ty| conv_type(ty) }), conv_type(ty[1]))
|
577
585
|
when :any then Type.any
|
578
586
|
when :void then Type::Void.new
|
579
587
|
when :nil then Type.nil
|
@@ -609,7 +617,7 @@ module TypeProf
|
|
609
617
|
end
|
610
618
|
when :union
|
611
619
|
tys = ty[1]
|
612
|
-
Type::Union.new(Utils::Set[*tys.map {|ty2| conv_type(ty2) }], nil) # XXX: Array and Hash support
|
620
|
+
Type::Union.new(Utils::Set[*tys.map {|ty2| conv_type(ty2) }], nil).normalize # XXX: Array and Hash support
|
613
621
|
when :var
|
614
622
|
Type::Var.new(ty[1])
|
615
623
|
when :proc
|
data/lib/typeprof/method.rb
CHANGED
@@ -11,6 +11,7 @@ module TypeProf
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
|
14
|
+
recv = recv.base_type while recv.respond_to?(:base_type)
|
14
15
|
recv = scratch.globalize_type(recv, caller_env, caller_ep)
|
15
16
|
aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
|
16
17
|
|
@@ -175,8 +176,10 @@ module TypeProf
|
|
175
176
|
ncaller_env = caller_env
|
176
177
|
#pp [mid, aargs, msig]
|
177
178
|
# XXX: support self type in msig
|
178
|
-
subst =
|
179
|
-
next unless
|
179
|
+
subst = aargs.consistent_with_method_signature?(msig)
|
180
|
+
next unless subst
|
181
|
+
# need to check self tyvar?
|
182
|
+
subst[Type::Var.new(:self)] = recv
|
180
183
|
case
|
181
184
|
when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
|
182
185
|
tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
|
@@ -205,22 +208,34 @@ module TypeProf
|
|
205
208
|
elems.update(nil, ty)
|
206
209
|
end
|
207
210
|
end
|
208
|
-
subst.merge!({ tyvar_elem => recv.elems.
|
211
|
+
subst.merge!({ tyvar_elem => recv.elems.squash })
|
209
212
|
when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
|
210
213
|
tyvar_k = Type::Var.new(:K)
|
211
214
|
tyvar_v = Type::Var.new(:V)
|
212
|
-
|
213
|
-
|
215
|
+
k_ty0, v_ty0 = recv.elems.squash
|
216
|
+
if subst[tyvar_k] && subst[tyvar_v]
|
217
|
+
k_ty = subst[tyvar_k]
|
218
|
+
v_ty = subst[tyvar_v]
|
219
|
+
k_ty0 = k_ty0.union(k_ty)
|
220
|
+
v_ty0 = v_ty0.union(v_ty)
|
221
|
+
alloc_site = AllocationSite.new(caller_ep)
|
222
|
+
ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
|
223
|
+
ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
|
224
|
+
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
225
|
+
elems.update(k_ty, v_ty)
|
226
|
+
end
|
227
|
+
end
|
214
228
|
# XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type?
|
215
|
-
subst.merge!({ tyvar_k =>
|
229
|
+
subst.merge!({ tyvar_k => k_ty0, tyvar_v => v_ty0 })
|
216
230
|
end
|
217
|
-
ret_ty = ret_ty.substitute(subst, Config.options[:type_depth_limit])
|
218
231
|
found = true
|
219
232
|
if aargs.blk_ty.is_a?(Type::Proc)
|
220
233
|
#raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
|
221
234
|
dummy_ctx = TypedContext.new(caller_ep, mid)
|
222
235
|
dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
|
223
|
-
|
236
|
+
s_recv = recv
|
237
|
+
s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
|
238
|
+
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
|
224
239
|
if msig.blk_ty.is_a?(Type::Proc)
|
225
240
|
scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
|
226
241
|
nfargs = msig.blk_ty.block_body.msig
|
@@ -240,13 +255,55 @@ module TypeProf
|
|
240
255
|
0.upto(nfargs.opt_tys.size) do |n|
|
241
256
|
naargs = ActualArguments.new(nlead_tys[0, nfargs.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
|
242
257
|
scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
|
243
|
-
subst2 =
|
244
|
-
if
|
245
|
-
|
258
|
+
subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
|
259
|
+
if subst2
|
260
|
+
subst2 = Type.merge_substitution(subst, subst2)
|
261
|
+
case
|
262
|
+
when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
|
263
|
+
tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
|
264
|
+
tyvars.each_with_index do |tyvar, idx|
|
265
|
+
ty = subst2[tyvar]
|
266
|
+
if ty
|
267
|
+
ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
|
268
|
+
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
269
|
+
elems.update(idx, ty)
|
270
|
+
end
|
271
|
+
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
272
|
+
end
|
273
|
+
end
|
274
|
+
tyvars.zip(recv.elems.elems) do |tyvar, elem|
|
275
|
+
if subst2[tyvar]
|
276
|
+
subst2[tyvar] = subst2[tyvar].union(elem)
|
277
|
+
else
|
278
|
+
subst2[tyvar] = elem
|
279
|
+
end
|
280
|
+
end
|
281
|
+
ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
|
282
|
+
when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
|
246
283
|
tyvar_elem = Type::Var.new(:Elem)
|
247
284
|
if subst2[tyvar_elem]
|
285
|
+
ty = subst2[tyvar_elem]
|
286
|
+
ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
|
287
|
+
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
288
|
+
elems.update(nil, ty)
|
289
|
+
end
|
290
|
+
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
291
|
+
end
|
292
|
+
ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
|
293
|
+
when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
|
294
|
+
tyvar_k = Type::Var.new(:K)
|
295
|
+
tyvar_v = Type::Var.new(:V)
|
296
|
+
k_ty0, v_ty0 = recv.elems.squash
|
297
|
+
if subst2[tyvar_k] && subst2[tyvar_v]
|
298
|
+
k_ty = subst2[tyvar_k]
|
299
|
+
v_ty = subst2[tyvar_v]
|
300
|
+
k_ty0 = k_ty0.union(k_ty)
|
301
|
+
v_ty0 = v_ty0.union(v_ty)
|
302
|
+
alloc_site = AllocationSite.new(caller_ep)
|
303
|
+
ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
|
304
|
+
ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
|
248
305
|
ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
|
249
|
-
elems.update(
|
306
|
+
elems.update(k_ty, v_ty)
|
250
307
|
end
|
251
308
|
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
|
252
309
|
end
|
@@ -274,6 +331,7 @@ module TypeProf
|
|
274
331
|
ctn[ret_ty, caller_ep, ncaller_env]
|
275
332
|
end
|
276
333
|
else
|
334
|
+
ret_ty = ret_ty.substitute(subst, Config.options[:type_depth_limit])
|
277
335
|
ret_ty = ret_ty.remove_type_vars
|
278
336
|
ctn[ret_ty, caller_ep, ncaller_env]
|
279
337
|
end
|
data/lib/typeprof/type.rb
CHANGED
@@ -20,16 +20,69 @@ module TypeProf
|
|
20
20
|
self
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def self.match?(ty1, ty2)
|
24
|
+
# both ty1 and ty2 should be global
|
25
|
+
# ty1 is always concrete; it should not have type variables
|
26
|
+
# ty2 might be abstract; it may have type variables
|
27
|
+
case ty2
|
28
|
+
when Type::Var
|
29
|
+
{ ty2 => ty1 }
|
30
|
+
when Type::Any
|
31
|
+
{}
|
27
32
|
when Type::Union
|
28
|
-
|
29
|
-
|
33
|
+
subst = nil
|
34
|
+
ty2.each_child_global do |ty2|
|
35
|
+
# this is very conservative to create subst:
|
36
|
+
# Type.match?( int | str, int | X) creates { X => int | str } but should be { X => str }???
|
37
|
+
subst2 = Type.match?(ty1, ty2)
|
38
|
+
next unless subst2
|
39
|
+
subst = Type.merge_substitution(subst, subst2)
|
40
|
+
end
|
41
|
+
subst
|
42
|
+
else
|
43
|
+
case ty1
|
44
|
+
when Type::Var then raise "should not occur"
|
45
|
+
when Type::Any
|
46
|
+
subst = {}
|
47
|
+
ty2.each_free_type_variable do |tyvar|
|
48
|
+
subst[tyvar] = Type.any
|
49
|
+
end
|
50
|
+
subst
|
51
|
+
when Type::Union
|
52
|
+
subst = nil
|
53
|
+
ty1.each_child_global do |ty1|
|
54
|
+
subst2 = Type.match?(ty1, ty2)
|
55
|
+
next unless subst2
|
56
|
+
subst = Type.merge_substitution(subst, subst2)
|
57
|
+
end
|
58
|
+
subst
|
59
|
+
else
|
60
|
+
if ty2.is_a?(Type::ContainerType)
|
61
|
+
# ty2 may have type variables
|
62
|
+
return nil if ty1.class != ty2.class
|
63
|
+
ty1.match?(ty2)
|
64
|
+
elsif ty1.is_a?(Type::ContainerType)
|
65
|
+
nil
|
66
|
+
else
|
67
|
+
ty1.consistent?(ty2) ? {} : nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.merge_substitution(subst1, subst2)
|
74
|
+
if subst1
|
75
|
+
subst1 = subst1.dup
|
76
|
+
subst2.each do |tyvar, ty|
|
77
|
+
if subst1[tyvar]
|
78
|
+
subst1[tyvar] = subst1[tyvar].union(ty)
|
79
|
+
else
|
80
|
+
subst1[tyvar] = ty
|
81
|
+
end
|
30
82
|
end
|
83
|
+
subst1
|
31
84
|
else
|
32
|
-
|
85
|
+
subst2
|
33
86
|
end
|
34
87
|
end
|
35
88
|
|
@@ -41,6 +94,9 @@ module TypeProf
|
|
41
94
|
yield self
|
42
95
|
end
|
43
96
|
|
97
|
+
def each_free_type_variable
|
98
|
+
end
|
99
|
+
|
44
100
|
def union(other)
|
45
101
|
return self if self == other # fastpath
|
46
102
|
|
@@ -118,10 +174,8 @@ module TypeProf
|
|
118
174
|
nil
|
119
175
|
end
|
120
176
|
|
121
|
-
def consistent?(
|
122
|
-
|
123
|
-
other.add_subst!(self, subst) if other.is_a?(Type::Var)
|
124
|
-
true
|
177
|
+
def consistent?(_other)
|
178
|
+
raise "should not be called"
|
125
179
|
end
|
126
180
|
|
127
181
|
def substitute(_subst, _depth)
|
@@ -156,6 +210,12 @@ module TypeProf
|
|
156
210
|
@elems = elems
|
157
211
|
end
|
158
212
|
|
213
|
+
def each_free_type_variable(&blk)
|
214
|
+
each_child_global do |ty|
|
215
|
+
ty.each_free_type_variable(&blk)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
159
219
|
def limit_size(limit)
|
160
220
|
return Type.any if limit <= 0
|
161
221
|
tys = Utils::Set[]
|
@@ -271,48 +331,20 @@ module TypeProf
|
|
271
331
|
def localize(env, alloc_site, depth)
|
272
332
|
return env, Type.any if depth <= 0
|
273
333
|
tys = @types.map do |ty|
|
274
|
-
|
275
|
-
env, ty2 = ty.localize(env, alloc_site2, depth - 1)
|
334
|
+
env, ty2 = ty.localize(env, alloc_site, depth - 1)
|
276
335
|
ty2
|
277
336
|
end
|
278
337
|
@elems&.each do |(container_kind, base_type), elems|
|
279
338
|
ty = container_kind.new(elems, base_type)
|
280
|
-
|
281
|
-
env, ty = ty.localize(env, alloc_site2, depth - 1)
|
339
|
+
env, ty = ty.localize(env, alloc_site, depth - 1)
|
282
340
|
tys = tys.add(ty)
|
283
341
|
end
|
284
342
|
ty = Union.new(tys, nil).normalize
|
285
343
|
return env, ty
|
286
344
|
end
|
287
345
|
|
288
|
-
def consistent?(
|
289
|
-
|
290
|
-
when Type::Any then true
|
291
|
-
when Type::Var then other.add_subst!(self, subst)
|
292
|
-
when Type::Union
|
293
|
-
# this is very conservative to create subst:
|
294
|
-
# consistent?( int | str, int | X) creates { X => int | str } but should be { X => str }???
|
295
|
-
@types.each do |ty1|
|
296
|
-
other.types.each do |ty2|
|
297
|
-
subst2 = subst.dup
|
298
|
-
if ty1.consistent?(ty2, subst2)
|
299
|
-
subst.replace(subst2)
|
300
|
-
# XXX: need to check other pairs to create conservative substitution??
|
301
|
-
# consistent?( X | :foo, str | int ) may return { X => str } or { X => int } but should be { X => str | int }?
|
302
|
-
return true
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
306
|
-
return true if @types.size == 0 && other.types.size == 0 # XXX: is this okay?
|
307
|
-
# TODO: array argument?
|
308
|
-
return false
|
309
|
-
else
|
310
|
-
@types.each do |ty1|
|
311
|
-
return true if ty1.consistent?(other, subst)
|
312
|
-
end
|
313
|
-
# TODO: array argument?
|
314
|
-
return false
|
315
|
-
end
|
346
|
+
def consistent?(_other)
|
347
|
+
raise "should not be called"
|
316
348
|
end
|
317
349
|
|
318
350
|
def substitute(subst, depth)
|
@@ -331,7 +363,7 @@ module TypeProf
|
|
331
363
|
elems = @elems&.to_h do |(container_kind, base_type), elems|
|
332
364
|
[[container_kind, base_type], elems.substitute(subst, depth - 1)]
|
333
365
|
end
|
334
|
-
ty = Union.new(tys, elems)
|
366
|
+
ty = Union.new(tys, elems).normalize
|
335
367
|
unions.each do |ty0|
|
336
368
|
ty = ty.union(ty0)
|
337
369
|
end
|
@@ -371,6 +403,10 @@ module TypeProf
|
|
371
403
|
"Var[#{ @name }]"
|
372
404
|
end
|
373
405
|
|
406
|
+
def each_free_type_variable
|
407
|
+
yield self
|
408
|
+
end
|
409
|
+
|
374
410
|
def substitute(subst, depth)
|
375
411
|
if subst[self]
|
376
412
|
subst[self].limit_size(depth)
|
@@ -379,7 +415,7 @@ module TypeProf
|
|
379
415
|
end
|
380
416
|
end
|
381
417
|
|
382
|
-
def consistent?(
|
418
|
+
def consistent?(_other)
|
383
419
|
raise "should not be called: #{ self }"
|
384
420
|
end
|
385
421
|
|
@@ -420,15 +456,8 @@ module TypeProf
|
|
420
456
|
scratch.get_method(self, true, mid)
|
421
457
|
end
|
422
458
|
|
423
|
-
def consistent?(other
|
459
|
+
def consistent?(other)
|
424
460
|
case other
|
425
|
-
when Type::Any then true
|
426
|
-
when Type::Var then other.add_subst!(self, subst)
|
427
|
-
when Type::Union
|
428
|
-
other.types.each do |ty|
|
429
|
-
return true if consistent?(ty, subst)
|
430
|
-
end
|
431
|
-
return false
|
432
461
|
when Type::Class
|
433
462
|
ty = self
|
434
463
|
loop do
|
@@ -479,17 +508,10 @@ module TypeProf
|
|
479
508
|
scratch.get_method(@klass, false, mid)
|
480
509
|
end
|
481
510
|
|
482
|
-
def consistent?(other
|
511
|
+
def consistent?(other)
|
483
512
|
case other
|
484
|
-
when Type::Any then true
|
485
|
-
when Type::Var then other.add_subst!(self, subst)
|
486
|
-
when Type::Union
|
487
|
-
other.types.each do |ty|
|
488
|
-
return true if consistent?(ty, subst)
|
489
|
-
end
|
490
|
-
return false
|
491
513
|
when Type::Instance
|
492
|
-
@klass.consistent?(other.klass
|
514
|
+
@klass.consistent?(other.klass)
|
493
515
|
when Type::Class
|
494
516
|
return true if @klass == Type::Builtin[:obj] || @klass == Type::Builtin[:class] || @klass == Type::Builtin[:module]
|
495
517
|
return false
|
@@ -503,6 +525,7 @@ module TypeProf
|
|
503
525
|
end
|
504
526
|
end
|
505
527
|
|
528
|
+
# This is an internal object in MRI, so a user program cannot create this object explicitly
|
506
529
|
class ISeq < Type
|
507
530
|
def initialize(iseq)
|
508
531
|
@iseq = iseq
|
@@ -520,20 +543,14 @@ module TypeProf
|
|
520
543
|
end
|
521
544
|
|
522
545
|
class Proc < Type
|
523
|
-
def initialize(block_body,
|
524
|
-
@block_body, @
|
546
|
+
def initialize(block_body, base_type)
|
547
|
+
@block_body, @base_type = block_body, base_type
|
525
548
|
end
|
526
549
|
|
527
|
-
attr_reader :block_body, :
|
550
|
+
attr_reader :block_body, :base_type
|
528
551
|
|
529
|
-
def consistent?(other
|
552
|
+
def consistent?(other)
|
530
553
|
case other
|
531
|
-
when Type::Any then true
|
532
|
-
when Type::Var then other.add_subst!(self, subst)
|
533
|
-
when Type::Union
|
534
|
-
other.types.each do |ty2|
|
535
|
-
return true if consistent?(ty2, subst)
|
536
|
-
end
|
537
554
|
when Type::Proc
|
538
555
|
@block_body.consistent?(other.block_body)
|
539
556
|
else
|
@@ -542,11 +559,11 @@ module TypeProf
|
|
542
559
|
end
|
543
560
|
|
544
561
|
def get_method(mid, scratch)
|
545
|
-
@
|
562
|
+
@base_type.get_method(mid, scratch)
|
546
563
|
end
|
547
564
|
|
548
565
|
def substitute(subst, depth)
|
549
|
-
Proc.new(@block_body.substitute(subst, depth), @
|
566
|
+
Proc.new(@block_body.substitute(subst, depth), @base_type)
|
550
567
|
end
|
551
568
|
|
552
569
|
def screen_name(scratch)
|
@@ -566,14 +583,12 @@ module TypeProf
|
|
566
583
|
"Type::Symbol[#{ @sym ? @sym.inspect : "(dynamic symbol)" }, #{ @base_type.inspect }]"
|
567
584
|
end
|
568
585
|
|
569
|
-
def consistent?(other
|
586
|
+
def consistent?(other)
|
570
587
|
case other
|
571
|
-
when Var
|
572
|
-
other.add_subst!(self, subst)
|
573
588
|
when Symbol
|
574
589
|
@sym == other.sym
|
575
590
|
else
|
576
|
-
@base_type.consistent?(other
|
591
|
+
@base_type.consistent?(other)
|
577
592
|
end
|
578
593
|
end
|
579
594
|
|
@@ -594,33 +609,33 @@ module TypeProf
|
|
594
609
|
end
|
595
610
|
end
|
596
611
|
|
597
|
-
# local
|
612
|
+
# A local type
|
598
613
|
class Literal < Type
|
599
|
-
def initialize(lit,
|
614
|
+
def initialize(lit, base_type)
|
600
615
|
@lit = lit
|
601
|
-
@
|
616
|
+
@base_type = base_type
|
602
617
|
end
|
603
618
|
|
604
|
-
attr_reader :lit, :
|
619
|
+
attr_reader :lit, :base_type
|
605
620
|
|
606
621
|
def inspect
|
607
|
-
"Type::Literal[#{ @lit.inspect }, #{ @
|
622
|
+
"Type::Literal[#{ @lit.inspect }, #{ @base_type.inspect }]"
|
608
623
|
end
|
609
624
|
|
610
625
|
def screen_name(scratch)
|
611
|
-
@
|
626
|
+
@base_type.screen_name(scratch) + "<#{ @lit.inspect }>"
|
612
627
|
end
|
613
628
|
|
614
629
|
def globalize(_env, _visited, _depth)
|
615
|
-
@
|
630
|
+
@base_type
|
616
631
|
end
|
617
632
|
|
618
633
|
def get_method(mid, scratch)
|
619
|
-
@
|
634
|
+
@base_type.get_method(mid, scratch)
|
620
635
|
end
|
621
636
|
|
622
|
-
def consistent?(
|
623
|
-
|
637
|
+
def consistent?(_other)
|
638
|
+
raise "should not called"
|
624
639
|
end
|
625
640
|
end
|
626
641
|
|