Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow limit_type_depth to introduce more than one new TypeVar #20626

Merged
merged 4 commits into from
Feb 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have been cov ? Any : (v = TypeVar(:_); push!(vars, v); v)? cc @martinholters

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable. I'll look into this...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR at #21192, but also needs #21191 fixed.

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