-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Self-recursive type definition with a Union segfaults #33709
Comments
Thanks for the detailed report; I'll take a look. |
@JeffBezanson, @vtjnash, @Keno (and whoever else may know/have an opinion), The issue here is when constructing Now, changing the if (jl_is_datatype(ty) && jl_datatype_isinlinealloc(ty) && (((jl_datatype_t *)ty)->layout)) {
size_t sz = jl_datatype_size(ty);
size_t al = jl_datatype_align(ty);
if (*nbytes < sz)
*nbytes = sz;
if (*align < al)
*align = al;
return 1;
} seems to do the trick, i.e. avoids allowing a recursive type to be marked I can put up a PR w/ the |
There’s already code there to prohibit inlining of recursive types. It’s currently run late, since the ordering didn’t use to matter. Apparently it should now run first. |
Maybe check my branch for mutually recursive fielstypes. I had to address a bunch of these kinds of issues there. |
As @vtjnash suggested, I tried to put the code preventing inlining of recursive types at the top of the function, and it does solve the problem. The entire diff is diff --git a/src/datatype.c b/src/datatype.c
index 9cf1ec58e0..fd0d8639aa 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -311,6 +311,18 @@ void jl_compute_field_offsets(jl_datatype_t *st)
// based on whether its definition is self-referential
if (w->types != NULL) {
st->isbitstype = st->isinlinealloc = st->isconcretetype && !st->mutabl;
+ if (st->isinlinealloc) {
+ size_t i, nf = jl_svec_len(w->types);
+ for (i = 0; i < nf; i++) {
+ jl_value_t *fld = jl_svecref(w->types, i);
+ if (references_name(fld, w->name)) {
+ st->isinlinealloc = 0;
+ st->isbitstype = 0;
+ st->zeroinit = 1;
+ break;
+ }
+ }
+ }
size_t i, nf = jl_svec_len(st->types);
for (i = 0; i < nf; i++) {
jl_value_t *fld = jl_svecref(st->types, i);
@@ -327,18 +339,6 @@ void jl_compute_field_offsets(jl_datatype_t *st)
st->has_concrete_subtype &= !jl_is_datatype(fld) || ((jl_datatype_t *)fld)->has_concrete_subtype;
}
}
- if (st->isinlinealloc) {
- size_t i, nf = jl_svec_len(w->types);
- for (i = 0; i < nf; i++) {
- jl_value_t *fld = jl_svecref(w->types, i);
- if (references_name(fld, w->name)) {
- st->isinlinealloc = 0;
- st->isbitstype = 0;
- st->zeroinit = 1;
- break;
- }
- }
- }
}
// If layout doesn't depend on type parameters, it's stored in st->name->wrapper
// and reused by all subtypes. I think this solution is the more specific option @quinnj was looking for, (but please correct me if I'm wrong!) so should I go ahead and make a PR? |
@Liozou, that’d be great! Thanks! |
Hi everyone! I just noticed that defining such a type segfaults:
yields
I don't have a particular use case for this but I believe this should at most error instead of segfaulting. Git-bisection shows that #32448 introduced this behaviour. This code for instance used to work (and is now broken):
Version info:
The text was updated successfully, but these errors were encountered: