Skip to content

Commit abd48cd

Browse files
committed
Make has_concrete_subtype a memoized property
Fixes #31062
1 parent 7b34f1b commit abd48cd

File tree

6 files changed

+30
-18
lines changed

6 files changed

+30
-18
lines changed

src/datatype.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ jl_datatype_t *jl_new_uninitialized_datatype(void)
8585
t->isbitstype = 0;
8686
t->zeroinit = 0;
8787
t->isinlinealloc = 0;
88+
t->has_concrete_subtype = 1;
8889
t->layout = NULL;
8990
t->names = NULL;
9091
return t;
@@ -309,6 +310,12 @@ void jl_compute_field_offsets(jl_datatype_t *st)
309310
st->isbitstype = jl_is_datatype(fld) && ((jl_datatype_t*)fld)->isbitstype;
310311
if (!st->zeroinit)
311312
st->zeroinit = (jl_is_datatype(fld) && ((jl_datatype_t*)fld)->isinlinealloc) ? ((jl_datatype_t*)fld)->zeroinit : 1;
313+
if (i < st->ninitialized) {
314+
if (fld == jl_bottom_type)
315+
st->has_concrete_subtype = 0;
316+
else
317+
st->has_concrete_subtype &= !jl_is_datatype(fld) || ((jl_datatype_t *)fld)->has_concrete_subtype;
318+
}
312319
}
313320
if (st->isbitstype) {
314321
st->isinlinealloc = 1;

src/dump.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_
369369
| (dt->isdispatchtuple << 2)
370370
| (dt->isbitstype << 3)
371371
| (dt->zeroinit << 4)
372-
| (dt->isinlinealloc << 5));
372+
| (dt->isinlinealloc << 5)
373+
| (dt->has_concrete_subtype << 6));
373374
if (!dt->abstract) {
374375
write_uint16(s->s, dt->ninitialized);
375376
}
@@ -1403,6 +1404,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v
14031404
dt->isbitstype = (memflags >> 3) & 1;
14041405
dt->zeroinit = (memflags >> 4) & 1;
14051406
dt->isinlinealloc = (memflags >> 5) & 1;
1407+
dt->has_concrete_subtype = (memflags >> 6) & 1;
14061408
dt->types = NULL;
14071409
dt->parameters = NULL;
14081410
dt->name = NULL;

src/gf.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,19 +2582,7 @@ int jl_has_concrete_subtype(jl_value_t *typ)
25822582
typ = jl_unwrap_vararg(typ);
25832583
if (!jl_is_datatype(typ))
25842584
return 1;
2585-
if (((jl_datatype_t*)typ)->name == jl_namedtuple_typename)
2586-
return jl_has_concrete_subtype(jl_tparam1(typ));
2587-
jl_svec_t *fields = jl_get_fieldtypes((jl_datatype_t*)typ);
2588-
size_t i, l = jl_svec_len(fields);
2589-
if (l != ((jl_datatype_t*)typ)->ninitialized)
2590-
if (((jl_datatype_t*)typ)->name != jl_tuple_typename)
2591-
return 1;
2592-
for (i = 0; i < l; i++) {
2593-
jl_value_t *ft = jl_svecref(fields, i);
2594-
if (!jl_has_concrete_subtype(ft))
2595-
return 0;
2596-
}
2597-
return 1;
2585+
return ((jl_datatype_t*)typ)->has_concrete_subtype;
25982586
}
25992587

26002588
// TODO: separate the codegen and typeinf locks

src/jltypes.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,7 @@ void jl_init_types(void) JL_GC_DISABLED
17071707
jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type;
17081708
jl_datatype_type->super = (jl_datatype_t*)jl_type_type;
17091709
jl_datatype_type->parameters = jl_emptysvec;
1710-
jl_datatype_type->name->names = jl_perm_symsvec(20,
1710+
jl_datatype_type->name->names = jl_perm_symsvec(21,
17111711
"name",
17121712
"super",
17131713
"parameters",
@@ -1726,9 +1726,10 @@ void jl_init_types(void) JL_GC_DISABLED
17261726
"isbitstype",
17271727
"zeroinit",
17281728
"isinlinealloc",
1729+
"has_concrete_subtype",
17291730
"llvm::StructType",
17301731
"llvm::DIType");
1731-
jl_datatype_type->types = jl_svec(20,
1732+
jl_datatype_type->types = jl_svec(21,
17321733
jl_typename_type,
17331734
jl_datatype_type,
17341735
jl_simplevector_type,
@@ -1737,7 +1738,7 @@ void jl_init_types(void) JL_GC_DISABLED
17371738
jl_any_type, jl_any_type, jl_any_type, jl_any_type,
17381739
jl_any_type, jl_any_type, jl_any_type, jl_any_type,
17391740
jl_any_type, jl_any_type, jl_any_type, jl_any_type,
1740-
jl_any_type, jl_any_type);
1741+
jl_any_type, jl_any_type, jl_any_type);
17411742
jl_datatype_type->instance = NULL;
17421743
jl_datatype_type->uid = jl_assign_type_uid();
17431744
jl_datatype_type->struct_decl = NULL;
@@ -2293,8 +2294,9 @@ void jl_init_types(void) JL_GC_DISABLED
22932294
jl_svecset(jl_datatype_type->types, 15, jl_bool_type);
22942295
jl_svecset(jl_datatype_type->types, 16, jl_bool_type);
22952296
jl_svecset(jl_datatype_type->types, 17, jl_bool_type);
2296-
jl_svecset(jl_datatype_type->types, 18, jl_voidpointer_type);
2297+
jl_svecset(jl_datatype_type->types, 18, jl_bool_type);
22972298
jl_svecset(jl_datatype_type->types, 19, jl_voidpointer_type);
2299+
jl_svecset(jl_datatype_type->types, 20, jl_voidpointer_type);
22982300
jl_svecset(jl_typename_type->types, 1, jl_module_type);
22992301
jl_svecset(jl_typename_type->types, 6, jl_long_type);
23002302
jl_svecset(jl_typename_type->types, 3, jl_type_type);

src/julia.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ typedef struct _jl_datatype_t {
442442
uint8_t isbitstype; // relevant query for C-api and type-parameters
443443
uint8_t zeroinit; // if one or more fields requires zero-initialization
444444
uint8_t isinlinealloc; // if this is allocated inline
445+
uint8_t has_concrete_subtype; // If clear, no value will have this datatype
445446
void *struct_decl; //llvm::Type*
446447
void *ditype; // llvm::MDNode* to be used as llvm::DIType(ditype)
447448
} jl_datatype_t;

test/core.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6976,3 +6976,15 @@ let spvec = sparse_t31649(zeros(Float64,5), Vector{Int64}())
69766976
@test convert(Any, nothing) === nothing
69776977
@test_throws MethodError repr(spvec)
69786978
end
6979+
6980+
# Issue #31062 - Accidental recursion in jl_has_concrete_subtype
6981+
struct Bar31062
6982+
x::NTuple{N, Bar31062} where N
6983+
end
6984+
struct Foo31062
6985+
x::Foo31062
6986+
end
6987+
# Use eval to make sure that this actually gets executed and not
6988+
# just constant folded by (future) over-eager compiler optimizations
6989+
@test isa(Core.eval(@__MODULE__, :(Bar31062(()))), Bar31062)
6990+
@test precompile(identity, (Foo31062,))

0 commit comments

Comments
 (0)