typeprof 0.4.2 → 0.5.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/.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
|
|