Skip to content

Commit fd02e4b

Browse files
committed
RFC: fix #41349: more accurate references_name
Marking this as RFC, since I am not certain that this is actually correct. Is the branch for `dp->types == NULL` that looks at the type parameters instead even needed here?
1 parent ed4c44f commit fd02e4b

File tree

2 files changed

+37
-15
lines changed

2 files changed

+37
-15
lines changed

src/builtins.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,26 +1487,36 @@ static int equiv_field_types(jl_value_t *old, jl_value_t *ft)
14871487
return 1;
14881488
}
14891489

1490-
static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layout) JL_NOTSAFEPOINT
1490+
static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layout, htable_t seen) JL_NOTSAFEPOINT
14911491
{
14921492
if (jl_is_uniontype(p))
1493-
return references_name(((jl_uniontype_t*)p)->a, name, affects_layout) ||
1494-
references_name(((jl_uniontype_t*)p)->b, name, affects_layout);
1493+
return references_name(((jl_uniontype_t*)p)->a, name, affects_layout, seen) ||
1494+
references_name(((jl_uniontype_t*)p)->b, name, affects_layout, seen);
14951495
if (jl_is_unionall(p))
1496-
return references_name((jl_value_t*)((jl_unionall_t*)p)->var, name, 0) ||
1497-
references_name(((jl_unionall_t*)p)->body, name, affects_layout);
1496+
return references_name((jl_value_t*)((jl_unionall_t*)p)->var, name, 0, seen) ||
1497+
references_name(((jl_unionall_t*)p)->body, name, affects_layout, seen);
14981498
if (jl_is_typevar(p))
1499-
return references_name(((jl_tvar_t*)p)->ub, name, 0) ||
1500-
references_name(((jl_tvar_t*)p)->lb, name, 0);
1499+
return references_name(((jl_tvar_t*)p)->ub, name, 0, seen) ||
1500+
references_name(((jl_tvar_t*)p)->lb, name, 0, seen);
15011501
if (jl_is_datatype(p)) {
15021502
jl_datatype_t *dp = (jl_datatype_t*)p;
15031503
if (affects_layout && dp->name == name)
15041504
return 1;
1505-
affects_layout = dp->types == NULL || jl_svec_len(dp->types) != 0;
1506-
size_t i, l = jl_nparams(p);
1507-
for (i = 0; i < l; i++) {
1508-
if (references_name(jl_tparam(p, i), name, affects_layout))
1509-
return 1;
1505+
jl_svec_t *ft = dp->types;
1506+
if (ft && !ptrhash_has(&seen, (void*)p)) {
1507+
ptrhash_put(&seen, (void*)p, (void*)2);
1508+
size_t i, l = jl_svec_len(ft);
1509+
for (i = 0; i < l; i++) {
1510+
if (references_name(jl_svecref(ft, i), name, 1, seen))
1511+
return 1;
1512+
}
1513+
}
1514+
else {
1515+
size_t i, l = jl_nparams(p);
1516+
for (i = 0; i < l; i++) {
1517+
if (references_name(jl_tparam(p, i), name, 1, seen))
1518+
return 1;
1519+
}
15101520
}
15111521
}
15121522
return 0;
@@ -1542,7 +1552,9 @@ JL_CALLABLE(jl_f__typebody)
15421552
size_t i, nf = jl_svec_len(ft);
15431553
for (i = 0; i < nf; i++) {
15441554
jl_value_t *fld = jl_svecref(ft, i);
1545-
if (references_name(fld, dt->name, 1)) {
1555+
htable_t seen;
1556+
htable_new(&seen, 32);
1557+
if (references_name(fld, dt->name, 1, seen)) {
15461558
dt->name->mayinlinealloc = 0;
15471559
break;
15481560
}

test/core.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7219,8 +7219,8 @@ end
72197219
struct B33954
72207220
x::Q33954{B33954}
72217221
end
7222-
@test_broken isbitstype(Tuple{B33954})
7223-
@test_broken isbitstype(B33954)
7222+
@test isbitstype(Tuple{B33954})
7223+
@test isbitstype(B33954)
72247224

72257225
struct B40050 <: Ref{Tuple{B40050}}
72267226
end
@@ -7564,3 +7564,13 @@ const T35130 = Tuple{Vector{Int}, <:Any}
75647564
end
75657565
h35130(x) = A35130(Any[x][1]::Vector{T35130})
75667566
@test h35130(T35130[([1],1)]) isa A35130
7567+
7568+
# issue #41349
7569+
struct A41349{T}
7570+
x::Ptr{T}
7571+
end
7572+
struct B41349
7573+
x::A41349{B41349}
7574+
end
7575+
@test isbitstype(B41349)
7576+
@test isbitstype(Tuple{B41349})

0 commit comments

Comments
 (0)