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

fix #33954, recursion through field types in is_derived_type #34223

Merged
merged 1 commit into from
Jan 2, 2020
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
15 changes: 0 additions & 15 deletions base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,6 @@ function is_derived_type(@nospecialize(t), @nospecialize(c), mindepth::Int)
for p in cP
is_derived_type(t, p, mindepth) && return true
end
if isconcretetype(c) && isbitstype(c)
# see if it was extracted from a fieldtype
# however, only look through types that can be inlined
# to ensure monotonicity of derivation
# since we know that for immutable, concrete, bits types,
# the field types must have been constructed prior to the type,
# it cannot have a reference cycle in the type graph
cF = c.types
for f in cF
# 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
return false
end
Expand Down
3 changes: 3 additions & 0 deletions src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ static int references_name(jl_value_t *p, jl_typename_t *name) JL_NOTSAFEPOINT
if (jl_is_datatype(p)) {
if (((jl_datatype_t*)p)->name == name)
return 1;
if (((jl_datatype_t*)p)->layout && jl_datatype_nfields(p) == 0)
return 0;
size_t i, l = jl_nparams(p);
for (i = 0; i < l; i++) {
if (references_name(jl_tparam(p, i), name))
Expand Down Expand Up @@ -401,6 +403,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
jl_value_t *fld = jl_svecref(w->types, i);
if (references_name(fld, w->name)) {
isinlinealloc = 0;
isbitstype = 0;
break;
}
}
Expand Down
7 changes: 7 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2485,3 +2485,10 @@ end
# constant prop of `Symbol("")`
f_getf_computed_symbol(p) = getfield(p, Symbol("first"))
@test Base.return_types(f_getf_computed_symbol, Tuple{Pair{Int8,String}}) == [Int8]

# issue #33954
struct X33954
x::Ptr{X33954}
end
f33954(x) = rand(Bool) ? f33954((x,)) : x
@test Base.return_types(f33954, Tuple{X33954})[1] >: X33954
16 changes: 16 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7140,3 +7140,19 @@ end
struct SplatBadIterate; end
Base.iterate(s::SplatBadIterate, args...) = ()
@test_throws BoundsError (SplatBadIterate()...,)

# issue #33954, layout with circular type parameters but not fields
struct P33954{T}
end
struct A33954
x::P33954{A33954}
end
@test isbitstype(Tuple{A33954})
struct Q33954{T}
x::Int
end
struct B33954
x::Q33954{B33954}
end
@test_broken isbitstype(Tuple{B33954})
@test_broken isbitstype(B33954)