Skip to content

Commit

Permalink
Allow limit_type_depth to introduce more than one new TypeVar (#2…
Browse files Browse the repository at this point in the history
…0626)

Allow `limit_type_depth` to introduce more than one new `TypeVar`

Assert `limit_type_depth` returns a supertype of its input

Fixes #20615.
  • Loading branch information
martinholters authored and JeffBezanson committed Feb 20, 2017
1 parent fec29e7 commit eb504bb
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 11 deletions.
30 changes: 19 additions & 11 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -660,21 +660,27 @@ function type_depth(t::ANY)
return 0
end

function limit_type_depth(t::ANY, d::Int, cov::Bool=true, var::Union{Void,TypeVar}=nothing)
function limit_type_depth(t::ANY, d::Int)
r = limit_type_depth(t, d, true, TypeVar[])
@assert !isa(t, Type) || t <: r
return r
end

function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeVar[])
if isa(t,Union)
if d > MAX_TYPE_DEPTH
return Any
end
return Union{map(x->limit_type_depth(x, d+1, cov, var), (t.a,t.b))...}
return Union{map(x->limit_type_depth(x, d+1, cov, vars), (t.a,t.b))...}
elseif isa(t,UnionAll)
v = t.var
if v.ub === Any
if v.lb === Bottom
return UnionAll(t.var, limit_type_depth(t.body, d, cov, var))
return UnionAll(t.var, limit_type_depth(t.body, d, cov, vars))
end
ub = Any
else
ub = limit_type_depth(v.ub, d+1, true, nothing)
ub = limit_type_depth(v.ub, d+1, true)
end
if v.lb === Bottom || type_depth(v.lb) > MAX_TYPE_DEPTH
# note: lower bounds need to be widened by making them lower
Expand All @@ -683,25 +689,27 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool=true, var::Union{Void,TypeVa
lb = v.lb
end
v2 = TypeVar(v.name, lb, ub)
return UnionAll(v2, limit_type_depth(t{v2}, d, cov, var))
return UnionAll(v2, limit_type_depth(t{v2}, d, cov, vars))
elseif !isa(t,DataType)
return t
end
P = t.parameters
isempty(P) && return t
if d > MAX_TYPE_DEPTH
cov && return t.name.wrapper
# TODO mutating a TypeVar is not great style
var.ub = t.name.wrapper
var = TypeVar(:_, t.name.wrapper)
push!(vars, var)
return var
end
stillcov = cov && (t.name === Tuple.name)
Q = map(x->limit_type_depth(x, d+1, stillcov, vars), P)
R = t.name.wrapper{Q...}
if cov && !stillcov
var = TypeVar(:_)
for var in vars
R = UnionAll(var, R)
end
end
Q = map(x->limit_type_depth(x, d+1, stillcov, var), P)
R = t.name.wrapper{Q...}
return (cov && !stillcov) ? UnionAll(var, R) : R
return R
end

const DataType_name_fieldindex = fieldindex(DataType, :name)
Expand Down
6 changes: 6 additions & 0 deletions test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -642,3 +642,9 @@ end
# infinite type growth via lower bounds (formed by intersection)
f20267(x::T20267{T}, y::T) where (T) = f20267(Any[1][1], x.inds)
@test Base.return_types(f20267, (Any, Any)) == Any[Union{}]

# issue #20615
let A = 1:2, z = zip(A, A, A, A, A, A, A, A, A, A, A, A)
@test z isa Core.Inference.limit_type_depth(typeof(z), 0)
@test start(z) == (1, (1, (1, (1, (1, (1, (1, (1, (1, (1, (1, 1)))))))))))
end

0 comments on commit eb504bb

Please sign in to comment.