Skip to content

Commit

Permalink
fix another bug in circular type detection (#41516)
Browse files Browse the repository at this point in the history
Co-authored-by: Jeff Bezanson <[email protected]>
  • Loading branch information
vtjnash and JeffBezanson authored Jul 13, 2021
1 parent 84934e6 commit 1c92e0d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
35 changes: 28 additions & 7 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1487,22 +1487,38 @@ static int equiv_field_types(jl_value_t *old, jl_value_t *ft)
return 1;
}

// If a field can reference its enclosing type, then the inlining
// recursive depth is not statically bounded for some layouts, so we cannot
// inline it. The only way fields can reference this type (due to
// syntax-enforced restrictions) is via being passed as a type parameter. Thus
// we can conservatively check this by examining only the parameters of the
// dependent types.
// affects_layout is a hack introduced by #35275 to workaround a problem
// introduced by #34223: it checks whether we will potentially need to
// compute the layout of the object before we have fully computed the types of
// the fields during recursion over the allocation of the parameters for the
// field types (of the concrete subtypes)
static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layout) JL_NOTSAFEPOINT
{
if (jl_is_uniontype(p))
return references_name(((jl_uniontype_t*)p)->a, name, affects_layout) ||
references_name(((jl_uniontype_t*)p)->b, name, affects_layout);
if (jl_is_unionall(p))
return references_name((jl_value_t*)((jl_unionall_t*)p)->var, name, 0) ||
return references_name((jl_value_t*)((jl_unionall_t*)p)->var->lb, name, 0) ||
references_name((jl_value_t*)((jl_unionall_t*)p)->var->ub, name, 0) ||
references_name(((jl_unionall_t*)p)->body, name, affects_layout);
if (jl_is_typevar(p))
return references_name(((jl_tvar_t*)p)->ub, name, 0) ||
references_name(((jl_tvar_t*)p)->lb, name, 0);
return 0; // already checked by unionall, if applicable
if (jl_is_datatype(p)) {
jl_datatype_t *dp = (jl_datatype_t*)p;
if (affects_layout && dp->name == name)
return 1;
affects_layout = dp->types == NULL || jl_svec_len(dp->types) != 0;
// affects_layout checks whether we will need to attempt to layout this
// type (based on whether all copies of it have the same layout) in
// that case, we still need to check the recursive parameters for
// layout recursion happening also, but we know it won't itself cause
// problems for the layout computation
affects_layout = ((jl_datatype_t*)jl_unwrap_unionall(dp->name->wrapper))->layout == NULL;
size_t i, l = jl_nparams(p);
for (i = 0; i < l; i++) {
if (references_name(jl_tparam(p, i), name, affects_layout))
Expand Down Expand Up @@ -1537,16 +1553,21 @@ JL_CALLABLE(jl_f__typebody)
else {
dt->types = (jl_svec_t*)ft;
jl_gc_wb(dt, ft);
if (!dt->name->mutabl) {
dt->name->mayinlinealloc = 1;
// If a supertype can reference the same type, then we may not be
// able to compute the layout of the object before needing to
// publish it, so we must assume it cannot be inlined, if that
// check passes, then we also still need to check the fields too.
if (!dt->name->mutabl && !references_name((jl_value_t*)dt->super, dt->name, 1)) {
int mayinlinealloc = 1;
size_t i, nf = jl_svec_len(ft);
for (i = 0; i < nf; i++) {
jl_value_t *fld = jl_svecref(ft, i);
if (references_name(fld, dt->name, 1)) {
dt->name->mayinlinealloc = 0;
mayinlinealloc = 0;
break;
}
}
dt->name->mayinlinealloc = mayinlinealloc;
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7219,8 +7219,17 @@ end
struct B33954
x::Q33954{B33954}
end
@test_broken isbitstype(Tuple{B33954})
@test_broken isbitstype(B33954)
@test isbitstype(Tuple{B33954})
@test isbitstype(B33954)

struct A41503{d}
e::d
end
struct B41503{j,k} <: AbstractArray{A41503{B41503{Any,k}},Any}
l::k
end
@test !isbitstype(B41503{Any,Any})
@test_broken isbitstype(B41503{Any,Int})

struct B40050 <: Ref{Tuple{B40050}}
end
Expand Down

0 comments on commit 1c92e0d

Please sign in to comment.