Skip to content

Commit 568e920

Browse files
JeffBezansonKristofferC
authored andcommitted
fix #31663, long inference time printing large tree structure (#31680)
- avoid exponential search in `is_derived_type` when parameters are used as field types - avoid inferring `show_default` - improve a fast path in subtyping (cherry picked from commit b2b35e9)
1 parent eb5059b commit 568e920

File tree

5 files changed

+35
-2
lines changed

5 files changed

+35
-2
lines changed

base/compiler/typelimits.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ function is_derived_type(@nospecialize(t), @nospecialize(c), mindepth::Int)
6666
# it cannot have a reference cycle in the type graph
6767
cF = c.types
6868
for f in cF
69-
is_derived_type(t, f, mindepth) && return true
69+
# often a parameter is also a field type; avoid searching twice
70+
if !contains_is(c.parameters, f)
71+
is_derived_type(t, f, mindepth) && return true
72+
end
7073
end
7174
end
7275
end

base/essentials.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,9 @@ function invokelatest(@nospecialize(f), @nospecialize args...; kwargs...)
794794
Core._apply_latest(inner)
795795
end
796796

797+
# TODO: possibly make this an intrinsic
798+
inferencebarrier(@nospecialize(x)) = Ref{Any}(x)[]
799+
797800
"""
798801
isempty(collection) -> Bool
799802

base/show.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,10 @@ show(x) = show(stdout::IO, x)
326326

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

329-
function show_default(io::IO, @nospecialize(x))
329+
# avoid inferring show_default on the type of `x`
330+
show_default(io::IO, @nospecialize(x)) = _show_default(io, inferencebarrier(x))
331+
332+
function _show_default(io::IO, @nospecialize(x))
330333
t = typeof(x)::DataType
331334
show(io, t)
332335
print(io, '(')

src/subtype.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ static int obviously_egal(jl_value_t *a, jl_value_t *b)
193193
if (jl_is_datatype(a)) {
194194
jl_datatype_t *ad = (jl_datatype_t*)a, *bd = (jl_datatype_t*)b;
195195
if (ad->name != bd->name) return 0;
196+
if (ad->isconcretetype || bd->isconcretetype) return 0;
196197
size_t i, np = jl_nparams(ad);
197198
if (np != jl_nparams(bd)) return 0;
198199
for(i=0; i < np; i++) {

test/compiler/inference.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,3 +2325,26 @@ h28762(::Type{X}) where {X} = Array{f28762(X)}(undef, 0)
23252325
@inferred g28762(Array)
23262326
@inferred h28762(Array)
23272327
end
2328+
2329+
# issue #31663
2330+
module I31663
2331+
abstract type AbstractNode end
2332+
2333+
struct Node{N1<:AbstractNode, N2<:AbstractNode} <: AbstractNode
2334+
a::N1
2335+
b::N2
2336+
end
2337+
2338+
struct Leaf <: AbstractNode
2339+
end
2340+
2341+
function gen_nodes(qty::Integer) :: AbstractNode
2342+
@assert qty > 0
2343+
result = Leaf()
2344+
for i in 1:qty
2345+
result = Node(result, Leaf())
2346+
end
2347+
return result
2348+
end
2349+
end
2350+
@test count(==('}'), string(I31663.gen_nodes(50))) == 1275

0 commit comments

Comments
 (0)