Skip to content

Commit

Permalink
Merge pull request #22627 from JuliaLang/jb/fix22624
Browse files Browse the repository at this point in the history
fix #22624, crash in certain circular type definitions

Ref #22627
(cherry picked from commit 05719b4)
  • Loading branch information
JeffBezanson authored and ararslan committed Sep 11, 2017
1 parent d711597 commit b59b38f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 24 deletions.
54 changes: 30 additions & 24 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,11 +827,7 @@ JL_DLLEXPORT jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *v)
}

typedef struct _jl_typestack_t {
union {
jl_value_t *ua;
jl_datatype_t *tt;
};
jl_value_t *ua_new;
jl_datatype_t *tt;
struct _jl_typestack_t *prev;
} jl_typestack_t;

Expand Down Expand Up @@ -999,8 +995,8 @@ static jl_value_t *normalize_vararg(jl_value_t *va)
return va;
}

static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp,
int cacheable, jl_typestack_t *stack, jl_typeenv_t *env)
static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp,
int cacheable, jl_typestack_t *stack, jl_typeenv_t *env)
{
jl_ptls_t ptls = jl_get_ptls_states();
jl_typestack_t top;
Expand Down Expand Up @@ -1198,6 +1194,25 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i
return (jl_value_t*)ndt;
}

// Build an environment mapping a TypeName's parameters to parameter values.
// This is the environment needed for instantiating a type's supertype and field types.
static jl_value_t *inst_datatype_env(jl_value_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp,
int cacheable, jl_typestack_t *stack, jl_typeenv_t *env, int c)
{
if (jl_is_datatype(dt))
return inst_datatype_inner((jl_datatype_t*)dt, p, iparams, ntp, cacheable, stack, env);
assert(jl_is_unionall(dt));
jl_unionall_t *ua = (jl_unionall_t*)dt;
jl_typeenv_t e = { ua->var, iparams[c], env };
return inst_datatype_env(ua->body, p, iparams, ntp, cacheable, stack, &e, c+1);
}

static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp,
int cacheable, jl_typestack_t *stack)
{
return inst_datatype_env(dt->name->wrapper, p, iparams, ntp, cacheable, stack, NULL, 0);
}

static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec_t *params)
{
int cacheable = 1;
Expand All @@ -1206,7 +1221,7 @@ static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec
cacheable = 0;
}
jl_datatype_t *ndt = (jl_datatype_t*)inst_datatype(jl_anytuple_type, params, p, np,
cacheable, NULL, NULL);
cacheable, NULL);
return ndt;
}

Expand All @@ -1222,12 +1237,12 @@ JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np)

jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p)
{
return (jl_datatype_t*)inst_datatype(jl_anytuple_type, p, jl_svec_data(p), jl_svec_len(p), 1, NULL, NULL);
return (jl_datatype_t*)inst_datatype(jl_anytuple_type, p, jl_svec_data(p), jl_svec_len(p), 1, NULL);
}

jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np)
{
return (jl_datatype_t*)inst_datatype(jl_anytuple_type, NULL, p, np, 1, NULL, NULL);
return (jl_datatype_t*)inst_datatype(jl_anytuple_type, NULL, p, np, 1, NULL);
}

static jl_svec_t *inst_all(jl_svec_t *p, jl_typeenv_t *env, jl_typestack_t *stack, int check)
Expand Down Expand Up @@ -1294,8 +1309,7 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
if (cacheable && !jl_is_leaf_type(pi))
cacheable = 0;
}
jl_value_t *result = inst_datatype((jl_datatype_t*)tt, ip_heap, iparams, ntp, cacheable,
stack, env);
jl_value_t *result = inst_datatype((jl_datatype_t*)tt, ip_heap, iparams, ntp, cacheable, stack);
JL_GC_POP();
return result;
}
Expand All @@ -1320,29 +1334,22 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
return (jl_value_t*)t;
}
if (jl_is_unionall(t)) {
jl_typestack_t *sp = stack;
while (sp != NULL) {
if (sp->ua == t)
return sp->ua_new;
sp = sp->prev;
}
if (!jl_has_free_typevars(t))
return t;
jl_unionall_t *ua = (jl_unionall_t*)t;
jl_value_t *res=NULL, *lb=ua->var->lb, *ub=ua->var->ub;
JL_GC_PUSH3(&lb, &ub, &res);
res = jl_new_struct(jl_unionall_type, ua->var, NULL);
jl_typestack_t top = { {t}, res, stack };
if (jl_has_bound_typevars(ua->var->lb, env))
lb = inst_type_w_(ua->var->lb, env, &top, check);
lb = inst_type_w_(ua->var->lb, env, stack, check);
if (jl_has_bound_typevars(ua->var->ub, env))
ub = inst_type_w_(ua->var->ub, env, &top, check);
ub = inst_type_w_(ua->var->ub, env, stack, check);
if (lb != ua->var->lb || ub != ua->var->ub) {
((jl_unionall_t*)res)->var = jl_new_typevar(ua->var->name, lb, ub);
jl_gc_wb(res, ((jl_unionall_t*)res)->var);
}
jl_typeenv_t newenv = { ua->var, (jl_value_t*)((jl_unionall_t*)res)->var, env };
jl_value_t *newbody = inst_type_w_(ua->body, &newenv, &top, check);
jl_value_t *newbody = inst_type_w_(ua->body, &newenv, stack, check);
if (newbody == (jl_value_t*)jl_emptytuple_type) {
// NTuple{0} => Tuple{} can make a typevar disappear
res = (jl_value_t*)jl_emptytuple_type;
Expand Down Expand Up @@ -1394,8 +1401,7 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t
// if t's parameters are not bound in the environment, return it uncopied (#9378)
if (!bound) { JL_GC_POP(); return (jl_value_t*)t; }

jl_value_t *result = inst_datatype((jl_datatype_t*)tt, NULL, iparams, ntp, cacheable,
stack, env);
jl_value_t *result = inst_datatype((jl_datatype_t*)tt, NULL, iparams, ntp, cacheable, stack);
JL_GC_POP();
return result;
}
Expand Down
10 changes: 10 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,16 @@ struct C21923{T,N}; v::C21923{T,M} where M; end
struct D21923{T,N}; v::D21923{T}; end
@test fieldtype(D21923, 1) == D21923

# issue #22624, more circular definitions
struct T22624{A,B,C}; v::Vector{T22624{Int64,A}}; end
let elT = T22624.body.body.body.types[1].parameters[1]
@test elT == T22624{Int64, T22624.var, C} where C
elT2 = elT.body.types[1].parameters[1]
@test elT2 == T22624{Int64, Int64, C} where C
@test elT2.body.types[1].parameters[1] === elT2
@test isleaftype(elT2.body.types[1])
end

# issue #3890
mutable struct A3890{T1}
x::Matrix{Complex{T1}}
Expand Down

0 comments on commit b59b38f

Please sign in to comment.