typeprof 0.4.2 → 0.5.4
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 +3 -3
- data/README.md +6 -0
- data/lib/typeprof/analyzer.rb +97 -84
- data/lib/typeprof/arguments.rb +27 -19
- data/lib/typeprof/block.rb +5 -2
- data/lib/typeprof/builtin.rb +14 -4
- data/lib/typeprof/config.rb +10 -6
- data/lib/typeprof/container-type.rb +117 -101
- data/lib/typeprof/export.rb +1 -1
- data/lib/typeprof/import.rb +44 -22
- data/lib/typeprof/method.rb +70 -12
- data/lib/typeprof/type.rb +108 -89
- data/lib/typeprof/version.rb +1 -1
- data/smoke/arguments2.rb +1 -1
- data/smoke/array11.rb +1 -1
- data/smoke/array6.rb +2 -2
- data/smoke/array8.rb +1 -1
- data/smoke/block-args2.rb +3 -3
- data/smoke/block-args3.rb +4 -4
- data/smoke/block-blockarg.rb +1 -1
- data/smoke/block-kwarg.rb +1 -1
- data/smoke/block10.rb +1 -1
- data/smoke/block5.rb +1 -1
- data/smoke/constant2.rb +1 -2
- data/smoke/demo5.rb +1 -1
- data/smoke/demo9.rb +1 -1
- data/smoke/hash-fetch.rb +3 -3
- data/smoke/hash-merge-bang.rb +11 -0
- data/smoke/hash1.rb +3 -2
- data/smoke/hash3.rb +1 -1
- data/smoke/inheritance2.rb +2 -2
- data/smoke/ivar2.rb +2 -2
- data/smoke/kernel-class.rb +1 -1
- data/smoke/keyword4.rb +1 -1
- data/smoke/kwsplat1.rb +2 -2
- data/smoke/kwsplat2.rb +1 -1
- data/smoke/multiple-superclass.rb +1 -1
- data/smoke/parameterizedd-self.rb +2 -2
- 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/struct.rb +2 -2
- data/smoke/uninitialize-var.rb +12 -0
- data/smoke/union-recv.rb +2 -2
- data/typeprof.gemspec +1 -1
- metadata +11 -4
data/lib/typeprof/block.rb
CHANGED
@@ -85,10 +85,13 @@ module TypeProf
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &ctn)
|
88
|
-
|
89
|
-
|
88
|
+
aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
|
89
|
+
subst = aargs.consistent_with_method_signature?(@msig)
|
90
|
+
unless subst
|
90
91
|
scratch.warn(caller_ep, "The arguments is not compatibile to RBS block")
|
91
92
|
end
|
93
|
+
# check?
|
94
|
+
#subst = { Type::Var.new(:self) => caller_env.static_env.recv_ty }
|
92
95
|
# XXX: Update type vars
|
93
96
|
ctn[@ret_ty, caller_ep, caller_env]
|
94
97
|
end
|
data/lib/typeprof/builtin.rb
CHANGED
@@ -54,6 +54,10 @@ module TypeProf
|
|
54
54
|
ctn[ret_ty, ep, env]
|
55
55
|
end
|
56
56
|
|
57
|
+
def vmcore_raise(recv, mid, aargs, ep, env, scratch, &ctn)
|
58
|
+
# no-op
|
59
|
+
end
|
60
|
+
|
57
61
|
def lambda(recv, mid, aargs, ep, env, scratch, &ctn)
|
58
62
|
ctn[aargs.blk_ty, ep, env]
|
59
63
|
end
|
@@ -63,10 +67,11 @@ module TypeProf
|
|
63
67
|
end
|
64
68
|
|
65
69
|
def object_s_new(recv, mid, aargs, ep, env, scratch, &ctn)
|
66
|
-
ty = Type::Instance.new(recv)
|
67
70
|
if recv.type_params.size >= 1
|
68
|
-
ty = Type::
|
71
|
+
ty = Type::ContainerType.create_empty_instance(recv)
|
69
72
|
env, ty = scratch.localize_type(ty, env, ep, AllocationSite.new(ep).add_id(:object_s_new))
|
73
|
+
else
|
74
|
+
ty = Type::Instance.new(recv)
|
70
75
|
end
|
71
76
|
meths = scratch.get_method(recv, false, :initialize)
|
72
77
|
meths.flat_map do |meth|
|
@@ -149,7 +154,11 @@ module TypeProf
|
|
149
154
|
|
150
155
|
def module_include(recv, mid, aargs, ep, env, scratch, &ctn)
|
151
156
|
arg = aargs.lead_tys[0]
|
152
|
-
|
157
|
+
arg.each_child do |arg|
|
158
|
+
if arg.is_a?(Type::Class)
|
159
|
+
scratch.include_module(recv, arg, false, ep.ctx.iseq.absolute_path)
|
160
|
+
end
|
161
|
+
end
|
153
162
|
ctn[recv, ep, env]
|
154
163
|
end
|
155
164
|
|
@@ -157,7 +166,7 @@ module TypeProf
|
|
157
166
|
arg = aargs.lead_tys[0]
|
158
167
|
arg.each_child do |arg|
|
159
168
|
if arg.is_a?(Type::Class)
|
160
|
-
scratch.
|
169
|
+
scratch.include_module(recv, arg, true, ep.ctx.iseq.absolute_path)
|
161
170
|
end
|
162
171
|
end
|
163
172
|
ctn[recv, ep, env]
|
@@ -520,6 +529,7 @@ module TypeProf
|
|
520
529
|
scratch.set_custom_method(klass_vmcore, :"core#set_method_alias", Builtin.method(:vmcore_set_method_alias))
|
521
530
|
scratch.set_custom_method(klass_vmcore, :"core#undef_method", Builtin.method(:vmcore_undef_method))
|
522
531
|
scratch.set_custom_method(klass_vmcore, :"core#hash_merge_kwd", Builtin.method(:vmcore_hash_merge_kwd))
|
532
|
+
scratch.set_custom_method(klass_vmcore, :"core#raise", Builtin.method(:vmcore_raise))
|
523
533
|
scratch.set_custom_method(klass_vmcore, :lambda, Builtin.method(:lambda))
|
524
534
|
scratch.set_singleton_custom_method(klass_obj, :"new", Builtin.method(:object_s_new))
|
525
535
|
scratch.set_singleton_custom_method(klass_obj, :"attr_accessor", Builtin.method(:module_attr_accessor))
|
data/lib/typeprof/config.rb
CHANGED
@@ -69,19 +69,23 @@ module TypeProf
|
|
69
69
|
prologue_ep = ExecutionPoint.new(prologue_ctx, -1, nil)
|
70
70
|
prologue_env = Env.new(StaticEnv.new(:top, Type.nil, false), [], [], Utils::HashWrapper.new({}))
|
71
71
|
|
72
|
-
Config.rb_files.each do |
|
73
|
-
if
|
74
|
-
iseq = ISeq.compile_str(
|
72
|
+
Config.rb_files.each do |rb|
|
73
|
+
if rb.is_a?(Array) # [String name, String content]
|
74
|
+
iseq = ISeq.compile_str(*rb.reverse)
|
75
75
|
else
|
76
|
-
iseq = ISeq.compile(
|
76
|
+
iseq = ISeq.compile(rb)
|
77
77
|
end
|
78
78
|
ep, env = TypeProf.starting_state(iseq)
|
79
79
|
scratch.merge_env(ep, env)
|
80
80
|
scratch.add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| }
|
81
81
|
end
|
82
82
|
|
83
|
-
Config.rbs_files.each do |
|
84
|
-
|
83
|
+
Config.rbs_files.each do |rbs|
|
84
|
+
if rbs.is_a?(Array) # [String name, String content]
|
85
|
+
Import.import_rbs_code(scratch, *rbs)
|
86
|
+
else
|
87
|
+
Import.import_rbs_file(scratch, rbs)
|
88
|
+
end
|
85
89
|
end
|
86
90
|
|
87
91
|
result = scratch.type_profile
|
@@ -19,13 +19,44 @@ module TypeProf
|
|
19
19
|
# Cell, Array, and Hash are types for global interface, e.g., TypedISeq.
|
20
20
|
# Do not push such types to local environment, stack, etc.
|
21
21
|
|
22
|
+
class ContainerType < Type
|
23
|
+
def match?(other)
|
24
|
+
return nil if self.class != other.class
|
25
|
+
return nil unless @base_type.consistent?(other.base_type)
|
26
|
+
@elems.match?(other.elems)
|
27
|
+
end
|
28
|
+
|
29
|
+
def each_free_type_variable(&blk)
|
30
|
+
@elems.each_free_type_variable(&blk)
|
31
|
+
end
|
32
|
+
|
33
|
+
def consistent?(other)
|
34
|
+
raise "must not be used"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.create_empty_instance(klass)
|
38
|
+
base_type = Type::Instance.new(klass)
|
39
|
+
case klass
|
40
|
+
when Type::Builtin[:ary] # XXX: check inheritance...
|
41
|
+
Type::Array.new(Type::Array::Elements.new([], Type.bot), base_type)
|
42
|
+
when Type::Builtin[:hash]
|
43
|
+
Type.gen_hash(base_type) {|h| }
|
44
|
+
else
|
45
|
+
Type::Cell.new(Type::Cell::Elements.new([Type.bot] * klass.type_params.size), base_type)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
22
50
|
# The most basic container type for default type parameter class
|
23
|
-
class Cell <
|
51
|
+
class Cell < ContainerType
|
24
52
|
def initialize(elems, base_type)
|
25
53
|
raise if !elems.is_a?(Cell::Elements)
|
26
54
|
@elems = elems # Cell::Elements
|
27
55
|
raise unless base_type
|
28
56
|
@base_type = base_type
|
57
|
+
if base_type.klass.type_params.size != elems.elems.size
|
58
|
+
raise
|
59
|
+
end
|
29
60
|
end
|
30
61
|
|
31
62
|
attr_reader :elems, :base_type
|
@@ -44,7 +75,7 @@ module TypeProf
|
|
44
75
|
|
45
76
|
def localize(env, alloc_site, depth)
|
46
77
|
return env, Type.any if depth <= 0
|
47
|
-
alloc_site = alloc_site.add_id(:cell)
|
78
|
+
alloc_site = alloc_site.add_id(:cell).add_id(@base_type)
|
48
79
|
env, elems = @elems.localize(env, alloc_site, depth)
|
49
80
|
env.deploy_type(LocalCell, alloc_site, elems, @base_type)
|
50
81
|
end
|
@@ -58,31 +89,13 @@ module TypeProf
|
|
58
89
|
raise
|
59
90
|
end
|
60
91
|
|
61
|
-
def consistent?(other, subst)
|
62
|
-
case other
|
63
|
-
when Type::Any then true
|
64
|
-
when Type::Var then other.add_subst!(self, subst)
|
65
|
-
when Type::Union
|
66
|
-
other.types.each do |ty2|
|
67
|
-
return true if consistent?(ty2, subst)
|
68
|
-
end
|
69
|
-
return false
|
70
|
-
when Type::Cell
|
71
|
-
@elems.size == other.elems.size &&
|
72
|
-
@base_type.consistent?(other.base_type, subst) &&
|
73
|
-
@elems.zip(other.elems).all? {|elem1, elem2| elem1..consistent?(elem2, subst) }
|
74
|
-
else
|
75
|
-
self == other
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
92
|
def substitute(subst, depth)
|
80
93
|
return Type.any if depth <= 0
|
81
94
|
elems = @elems.substitute(subst, depth)
|
82
95
|
Cell.new(elems, @base_type)
|
83
96
|
end
|
84
97
|
|
85
|
-
class Elements
|
98
|
+
class Elements # Cell
|
86
99
|
include Utils::StructuralEquality
|
87
100
|
|
88
101
|
def initialize(elems)
|
@@ -124,12 +137,21 @@ module TypeProf
|
|
124
137
|
end
|
125
138
|
end
|
126
139
|
|
127
|
-
def
|
128
|
-
|
140
|
+
def match?(other)
|
141
|
+
return nil if @elems.size != other.elems.size
|
142
|
+
subst = nil
|
129
143
|
@elems.zip(other.elems) do |ty0, ty1|
|
130
|
-
|
144
|
+
subst2 = Type.match?(ty0, ty1)
|
145
|
+
return nil unless subst2
|
146
|
+
subst = Type.merge_substitution(subst, subst2)
|
147
|
+
end
|
148
|
+
subst
|
149
|
+
end
|
150
|
+
|
151
|
+
def each_free_type_variable(&blk)
|
152
|
+
@elems.each do |ty|
|
153
|
+
ty.each_free_type_variable(&blk)
|
131
154
|
end
|
132
|
-
return true
|
133
155
|
end
|
134
156
|
|
135
157
|
def substitute(subst, depth)
|
@@ -146,6 +168,9 @@ module TypeProf
|
|
146
168
|
|
147
169
|
def union(other)
|
148
170
|
return self if self == other
|
171
|
+
if @elems.size != other.elems.size
|
172
|
+
raise "#{ @elems.size } != #{ other.elems.size }"
|
173
|
+
end
|
149
174
|
elems = []
|
150
175
|
@elems.zip(other.elems) do |ty0, ty1|
|
151
176
|
elems << ty0.union(ty1)
|
@@ -155,7 +180,7 @@ module TypeProf
|
|
155
180
|
end
|
156
181
|
end
|
157
182
|
|
158
|
-
class LocalCell <
|
183
|
+
class LocalCell < ContainerType
|
159
184
|
def initialize(id, base_type)
|
160
185
|
@id = id
|
161
186
|
raise unless base_type
|
@@ -184,6 +209,7 @@ module TypeProf
|
|
184
209
|
else
|
185
210
|
elems = Cell::Elements.new([]) # XXX
|
186
211
|
end
|
212
|
+
visited.delete(self)
|
187
213
|
Cell.new(elems, @base_type)
|
188
214
|
end
|
189
215
|
end
|
@@ -191,14 +217,10 @@ module TypeProf
|
|
191
217
|
def get_method(mid, scratch)
|
192
218
|
@base_type.get_method(mid, scratch)
|
193
219
|
end
|
194
|
-
|
195
|
-
def consistent?(other, subst)
|
196
|
-
raise "must not be used"
|
197
|
-
end
|
198
220
|
end
|
199
221
|
|
200
222
|
# Do not insert Array type to local environment, stack, etc.
|
201
|
-
class Array <
|
223
|
+
class Array < ContainerType
|
202
224
|
def initialize(elems, base_type)
|
203
225
|
raise unless elems.is_a?(Array::Elements)
|
204
226
|
@elems = elems # Array::Elements
|
@@ -223,7 +245,7 @@ module TypeProf
|
|
223
245
|
|
224
246
|
def localize(env, alloc_site, depth)
|
225
247
|
return env, Type.any if depth <= 0
|
226
|
-
alloc_site = alloc_site.add_id(:ary)
|
248
|
+
alloc_site = alloc_site.add_id(:ary).add_id(@base_type)
|
227
249
|
env, elems = @elems.localize(env, alloc_site, depth - 1)
|
228
250
|
env.deploy_type(LocalArray, alloc_site, elems, @base_type)
|
229
251
|
end
|
@@ -237,29 +259,13 @@ module TypeProf
|
|
237
259
|
raise
|
238
260
|
end
|
239
261
|
|
240
|
-
def consistent?(other, subst)
|
241
|
-
case other
|
242
|
-
when Type::Any then true
|
243
|
-
when Type::Var then other.add_subst!(self, subst)
|
244
|
-
when Type::Union
|
245
|
-
other.types.each do |ty2|
|
246
|
-
return true if consistent?(ty2, subst)
|
247
|
-
end
|
248
|
-
return false
|
249
|
-
when Type::Array
|
250
|
-
@base_type.consistent?(other.base_type, subst) && @elems.consistent?(other.elems, subst)
|
251
|
-
else
|
252
|
-
self == other
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
262
|
def substitute(subst, depth)
|
257
263
|
return Type.any if depth <= 0
|
258
264
|
elems = @elems.substitute(subst, depth - 1)
|
259
265
|
Array.new(elems, @base_type)
|
260
266
|
end
|
261
267
|
|
262
|
-
class Elements
|
268
|
+
class Elements # Array
|
263
269
|
include Utils::StructuralEquality
|
264
270
|
|
265
271
|
def initialize(lead_tys, rest_ty = Type.bot)
|
@@ -300,6 +306,9 @@ module TypeProf
|
|
300
306
|
|
301
307
|
def screen_name(scratch)
|
302
308
|
if Config.options[:show_container_raw_elements] || @rest_ty == Type.bot
|
309
|
+
if @lead_tys.empty?
|
310
|
+
return "Array[bot]" # RBS does not allow an empty tuple "[]"
|
311
|
+
end
|
303
312
|
s = @lead_tys.map do |ty|
|
304
313
|
ty.screen_name(scratch)
|
305
314
|
end
|
@@ -318,14 +327,24 @@ module TypeProf
|
|
318
327
|
end
|
319
328
|
end
|
320
329
|
|
321
|
-
def
|
330
|
+
def match?(other)
|
322
331
|
n = [@lead_tys.size, other.lead_tys.size].min
|
323
|
-
n.times do |i|
|
324
|
-
return false unless @lead_tys[i].consistent?(other.lead_tys[i], subst)
|
325
|
-
end
|
326
332
|
rest_ty1 = @lead_tys[n..].inject(@rest_ty) {|ty1, ty2| ty1.union(ty2) }
|
327
333
|
rest_ty2 = other.lead_tys[n..].inject(other.rest_ty) {|ty1, ty2| ty1.union(ty2) }
|
328
|
-
|
334
|
+
subst = nil
|
335
|
+
(@lead_tys[0, n] + [rest_ty1]).zip(other.lead_tys[0, n] + [rest_ty2]) do |ty0, ty1|
|
336
|
+
subst2 = Type.match?(ty0, ty1)
|
337
|
+
return nil unless subst2
|
338
|
+
subst = Type.merge_substitution(subst, subst2)
|
339
|
+
end
|
340
|
+
subst
|
341
|
+
end
|
342
|
+
|
343
|
+
def each_free_type_variable(&blk)
|
344
|
+
@lead_tys.each do |ty|
|
345
|
+
ty.each_free_type_variable(&blk)
|
346
|
+
end
|
347
|
+
@rest_ty&.each_free_type_variable(&blk)
|
329
348
|
end
|
330
349
|
|
331
350
|
def substitute(subst, depth)
|
@@ -476,7 +495,7 @@ module TypeProf
|
|
476
495
|
end
|
477
496
|
|
478
497
|
# Do not insert Array type to local environment, stack, etc.
|
479
|
-
class LocalArray <
|
498
|
+
class LocalArray < ContainerType
|
480
499
|
def initialize(id, base_type)
|
481
500
|
@id = id
|
482
501
|
raise unless base_type
|
@@ -506,6 +525,7 @@ module TypeProf
|
|
506
525
|
# TODO: currently out-of-scope array cannot be accessed
|
507
526
|
elems = Array::Elements.new([], Type.any)
|
508
527
|
end
|
528
|
+
visited.delete(self)
|
509
529
|
Array.new(elems, @base_type)
|
510
530
|
end
|
511
531
|
end
|
@@ -513,14 +533,10 @@ module TypeProf
|
|
513
533
|
def get_method(mid, scratch)
|
514
534
|
@base_type.get_method(mid, scratch)
|
515
535
|
end
|
516
|
-
|
517
|
-
def consistent?(other, subst)
|
518
|
-
raise "must not be used"
|
519
|
-
end
|
520
536
|
end
|
521
537
|
|
522
538
|
|
523
|
-
class Hash <
|
539
|
+
class Hash < ContainerType
|
524
540
|
def initialize(elems, base_type)
|
525
541
|
@elems = elems
|
526
542
|
raise unless elems
|
@@ -539,7 +555,7 @@ module TypeProf
|
|
539
555
|
|
540
556
|
def localize(env, alloc_site, depth)
|
541
557
|
return env, Type.any if depth <= 0
|
542
|
-
alloc_site = alloc_site.add_id(:hash)
|
558
|
+
alloc_site = alloc_site.add_id(:hash).add_id(@base_type)
|
543
559
|
env, elems = @elems.localize(env, alloc_site, depth - 1)
|
544
560
|
env.deploy_type(LocalHash, alloc_site, elems, @base_type)
|
545
561
|
end
|
@@ -553,29 +569,13 @@ module TypeProf
|
|
553
569
|
raise
|
554
570
|
end
|
555
571
|
|
556
|
-
def consistent?(other, subst)
|
557
|
-
case other
|
558
|
-
when Type::Any then true
|
559
|
-
when Type::Var then other.add_subst!(self, subst)
|
560
|
-
when Type::Union
|
561
|
-
other.types.each do |ty2|
|
562
|
-
return true if consistent?(ty2, subst)
|
563
|
-
end
|
564
|
-
return false
|
565
|
-
when Type::Hash
|
566
|
-
@base_type.consistent?(other.base_type, subst) && @elems.consistent?(other.elems, subst)
|
567
|
-
else
|
568
|
-
self == other
|
569
|
-
end
|
570
|
-
end
|
571
|
-
|
572
572
|
def substitute(subst, depth)
|
573
573
|
return Type.any if depth <= 0
|
574
574
|
elems = @elems.substitute(subst, depth - 1)
|
575
575
|
Hash.new(elems, @base_type)
|
576
576
|
end
|
577
577
|
|
578
|
-
class Elements
|
578
|
+
class Elements # Hash
|
579
579
|
include Utils::StructuralEquality
|
580
580
|
|
581
581
|
def initialize(map_tys)
|
@@ -634,12 +634,22 @@ module TypeProf
|
|
634
634
|
end
|
635
635
|
|
636
636
|
def screen_name(scratch)
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
637
|
+
if !@map_tys.empty? && @map_tys.all? {|k_ty,| k_ty.is_a?(Type::Symbol) }
|
638
|
+
s = @map_tys.map do |k_ty, v_ty|
|
639
|
+
v = v_ty.screen_name(scratch)
|
640
|
+
"#{ k_ty.sym }: #{ v }"
|
641
|
+
end.join(", ")
|
642
|
+
"{#{ s }}"
|
643
|
+
else
|
644
|
+
k_ty = v_ty = Type.bot
|
645
|
+
@map_tys.each do |k, v|
|
646
|
+
k_ty = k_ty.union(k)
|
647
|
+
v_ty = v_ty.union(v)
|
648
|
+
end
|
649
|
+
k_ty = k_ty.screen_name(scratch)
|
650
|
+
v_ty = v_ty.screen_name(scratch)
|
651
|
+
"Hash[#{ k_ty }, #{ v_ty }]"
|
652
|
+
end
|
643
653
|
end
|
644
654
|
|
645
655
|
def pretty_print(q)
|
@@ -657,22 +667,31 @@ module TypeProf
|
|
657
667
|
end
|
658
668
|
end
|
659
669
|
|
660
|
-
def
|
661
|
-
|
670
|
+
def match?(other)
|
671
|
+
subst = nil
|
662
672
|
other.map_tys.each do |k1, v1|
|
663
|
-
|
673
|
+
subst2 = nil
|
664
674
|
@map_tys.each do |k0, v0|
|
665
|
-
subst3 =
|
666
|
-
if
|
667
|
-
|
668
|
-
|
669
|
-
|
675
|
+
subst3 = Type.match?(k0, k1)
|
676
|
+
if subst3
|
677
|
+
subst4 = Type.match?(v0, v1)
|
678
|
+
if subst4
|
679
|
+
subst2 = Type.merge_substitution(subst2, subst3)
|
680
|
+
subst2 = Type.merge_substitution(subst2, subst4)
|
681
|
+
end
|
670
682
|
end
|
671
683
|
end
|
672
|
-
return
|
684
|
+
return nil unless subst2
|
685
|
+
subst = Type.merge_substitution(subst, subst2)
|
686
|
+
end
|
687
|
+
subst
|
688
|
+
end
|
689
|
+
|
690
|
+
def each_free_type_variable(&blk)
|
691
|
+
@map_tys.each do |k, v|
|
692
|
+
k.each_free_type_variable(&blk)
|
693
|
+
v.each_free_type_variable(&blk)
|
673
694
|
end
|
674
|
-
subst.replace(subst2)
|
675
|
-
true
|
676
695
|
end
|
677
696
|
|
678
697
|
def substitute(subst, depth)
|
@@ -706,7 +725,7 @@ module TypeProf
|
|
706
725
|
def [](key_ty)
|
707
726
|
val_ty = Type.bot
|
708
727
|
@map_tys.each do |k_ty, v_ty|
|
709
|
-
if
|
728
|
+
if Type.match?(k_ty, key_ty)
|
710
729
|
val_ty = val_ty.union(v_ty)
|
711
730
|
end
|
712
731
|
end
|
@@ -763,7 +782,7 @@ module TypeProf
|
|
763
782
|
end
|
764
783
|
end
|
765
784
|
|
766
|
-
class LocalHash <
|
785
|
+
class LocalHash < ContainerType
|
767
786
|
def initialize(id, base_type)
|
768
787
|
@id = id
|
769
788
|
@base_type = base_type
|
@@ -791,6 +810,7 @@ module TypeProf
|
|
791
810
|
else
|
792
811
|
elems = Hash::Elements.new({Type.any => Type.any})
|
793
812
|
end
|
813
|
+
visited.delete(self)
|
794
814
|
Hash.new(elems, @base_type)
|
795
815
|
end
|
796
816
|
end
|
@@ -798,10 +818,6 @@ module TypeProf
|
|
798
818
|
def get_method(mid, scratch)
|
799
819
|
@base_type.get_method(mid, scratch)
|
800
820
|
end
|
801
|
-
|
802
|
-
def consistent?(other, subst)
|
803
|
-
raise "must not be used"
|
804
|
-
end
|
805
821
|
end
|
806
822
|
end
|
807
823
|
end
|