Skip to content

Commit

Permalink
fix #31663, long inference time printing large tree structure
Browse files Browse the repository at this point in the history
- avoid exponential search in `is_derived_type` when parameters are
  used as field types
- avoid inferring `show_default`
- improve a fast path in subtyping
  • Loading branch information
JeffBezanson committed Apr 11, 2019
1 parent 29f61cd commit 8a6271b
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 2 deletions.
5 changes: 4 additions & 1 deletion base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ function is_derived_type(@nospecialize(t), @nospecialize(c), mindepth::Int)
# it cannot have a reference cycle in the type graph
cF = c.types
for f in cF
is_derived_type(t, f, mindepth) && return true
# often a parameter is also a field type; avoid searching twice
if !contains_is(c.parameters, f)
is_derived_type(t, f, mindepth) && return true
end
end
end
end
Expand Down
3 changes: 3 additions & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,9 @@ function invokelatest(@nospecialize(f), @nospecialize args...; kwargs...)
Core._apply_latest(inner)
end

# TODO: possibly make this an intrinsic
inferencebarrier(@nospecialize(x)) = Ref{Any}(x)[]

"""
isempty(collection) -> Bool
Expand Down
5 changes: 4 additions & 1 deletion base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,10 @@ show(x) = show(stdout::IO, x)

show(io::IO, @nospecialize(x)) = show_default(io, x)

function show_default(io::IO, @nospecialize(x))
# avoid inferring show_default on the type of `x`
show_default(io::IO, @nospecialize(x)) = _show_default(io, inferencebarrier(x))

function _show_default(io::IO, @nospecialize(x))
t = typeof(x)::DataType
show(io, t)
print(io, '(')
Expand Down
1 change: 1 addition & 0 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static int obviously_egal(jl_value_t *a, jl_value_t *b)
if (jl_is_datatype(a)) {
jl_datatype_t *ad = (jl_datatype_t*)a, *bd = (jl_datatype_t*)b;
if (ad->name != bd->name) return 0;
if (ad->isconcretetype || bd->isconcretetype) return 0;
size_t i, np = jl_nparams(ad);
if (np != jl_nparams(bd)) return 0;
for(i=0; i < np; i++) {
Expand Down
23 changes: 23 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2325,3 +2325,26 @@ h28762(::Type{X}) where {X} = Array{f28762(X)}(undef, 0)
@inferred g28762(Array)
@inferred h28762(Array)
end

# issue #31663
module I31663
abstract type AbstractNode end

struct Node{N1<:AbstractNode, N2<:AbstractNode} <: AbstractNode
a::N1
b::N2
end

struct Leaf <: AbstractNode
end

function gen_nodes(qty::Integer) :: AbstractNode
@assert qty > 0
result = Leaf()
for i in 1:qty
result = Node(result, Leaf())
end
return result
end
end
@test count(==('}'), string(I31663.gen_nodes(50))) == 1275

0 comments on commit 8a6271b

Please sign in to comment.