Skip to content

Commit db39be1

Browse files
committed
fix #5906
infinite type chain via field instantiation also a better fix for #5884
1 parent 7d056d2 commit db39be1

File tree

2 files changed

+64
-22
lines changed

2 files changed

+64
-22
lines changed

base/inference.jl

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -296,35 +296,50 @@ const tupleref_tfunc = function (A, t, i)
296296
end
297297
t_func[tupleref] = (2, 2, tupleref_tfunc)
298298

299-
function quantify_type(t, vars)
300-
# all types of the form S{...,T,...} in invariant position where T
301-
# is a bound variable are replaced with _<:S
299+
function limit_type_depth(t::ANY, d::Int, cov::Bool, vars)
302300
if isa(t,TypeVar) || isa(t,TypeConstructor)
303301
return t
304302
end
305303
if isa(t,Tuple)
306-
return map(x->quantify_type(x, vars), t)
307-
end
308-
if isa(t,UnionType)
309-
return Union(quantify_type(t.types, vars)...)
310-
end
311-
if isa(t,DataType)
304+
if d > MAX_TYPE_DEPTH
305+
R = Tuple
306+
else
307+
R = map(x->limit_type_depth(x, d+1, cov, vars), t)
308+
end
309+
elseif isa(t,UnionType)
310+
if d > MAX_TYPE_DEPTH
311+
R = Any
312+
else
313+
R = Union(limit_type_depth(t.types, d, cov, vars)...)
314+
end
315+
elseif isa(t,DataType)
312316
P = t.parameters
313317
if P === ()
314318
return t
315319
end
316-
P = quantify_type(P, vars)
317-
t = t.name.primary{P...}
318-
for i = 1:length(P)
319-
Pi = P[i]
320-
if isa(Pi,TypeVar) && contains_is(vars, Pi)
321-
return TypeVar(:_,t)
320+
if d > MAX_TYPE_DEPTH
321+
R = t.name.primary
322+
else
323+
Q = map(x->limit_type_depth(x, d+1, false, vars), P)
324+
if !cov && any(p->contains_is(vars,p), Q)
325+
R = TypeVar(:_,t.name.primary)
326+
push!(vars, R)
327+
return R
328+
else
329+
R = t.name.primary{Q...}
322330
end
323331
end
332+
else
333+
return t
324334
end
325-
return t
335+
if !cov && d > MAX_TYPE_DEPTH
336+
R = TypeVar(:_,R)
337+
push!(vars, R)
338+
end
339+
return R
326340
end
327341

342+
328343
const getfield_tfunc = function (A, s0, name)
329344
s = s0
330345
if isType(s)
@@ -362,11 +377,7 @@ const getfield_tfunc = function (A, s0, name)
362377
end
363378
for i=1:length(s.names)
364379
if is(s.names[i],fld)
365-
ft = s.types[i]
366-
if isleaftype(s) || !any(x->isa(x,TypeVar), s.parameters)
367-
return ft
368-
end
369-
return quantify_type(ft, s.parameters)
380+
return limit_type_depth(s.types[i], 0, true, {s.parameters...})
370381
end
371382
end
372383
return None
@@ -1165,6 +1176,9 @@ typeinf(linfo,atypes::ANY,sparams::ANY,def) = typeinf(linfo,atypes,sparams,def,t
11651176

11661177
CYCLE_ID = 1
11671178

1179+
#trace_inf = false
1180+
#enable_trace_inf() = (global trace_inf=true)
1181+
11681182
# def is the original unspecialized version of a method. we aggregate all
11691183
# saved type inference data there.
11701184
function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
@@ -1197,7 +1211,9 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
11971211
#if dbg
11981212
# print("typeinf ", linfo.name, " ", object_id(ast0), "\n")
11991213
#end
1200-
#print("typeinf ", linfo.name, " ", atypes, " ", linfo.file,":",linfo.line,"\n")
1214+
#if trace_inf
1215+
# print("typeinf ", linfo.name, " ", atypes, " ", linfo.file,":",linfo.line,"\n")
1216+
#end
12011217
# if isdefined(:STDOUT)
12021218
# write(STDOUT, "typeinf ")
12031219
# write(STDOUT, string(linfo.name))

test/core.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,3 +1380,29 @@ let
13801380
end
13811381
@test Test()() === nothing
13821382
end
1383+
1384+
# issue #5906
1385+
1386+
abstract Outer5906{T}
1387+
1388+
immutable Inner5906{T}
1389+
a:: T
1390+
end
1391+
1392+
immutable Empty5906{T} <: Outer5906{T}
1393+
end
1394+
1395+
immutable Hanoi5906{T} <: Outer5906{T}
1396+
a::T
1397+
succ :: Outer5906{Inner5906{T}}
1398+
Hanoi5906(a) = new(a, Empty5906{Inner5906{T}}())
1399+
end
1400+
1401+
function f5906{T}(h::Hanoi5906{T})
1402+
if isa(h.succ, Empty5906) return end
1403+
f5906(h.succ)
1404+
end
1405+
1406+
# can cause infinite recursion in type inference via instantiation of
1407+
# the type of the `succ` field
1408+
@test f5906(Hanoi5906{Int}(1)) === nothing

0 commit comments

Comments
 (0)