From 6b7e286c62f83b5ed92908134c9f1d405a682bd5 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 5 Dec 2022 14:11:14 -0500 Subject: [PATCH] compute env for typeintersect better Avoid discarding intermediate information sooner than we must (e.g. at return). --- src/jltypes.c | 2 +- src/julia.h | 2 +- src/subtype.c | 40 ++++++++++++++++++++-------------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/jltypes.c b/src/jltypes.c index b73d5ecab82aa..eb9eadca7b2d2 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1910,7 +1910,7 @@ jl_datatype_t *jl_wrap_Type(jl_value_t *t) jl_vararg_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n) { if (n) { - if (jl_is_typevar(n)) { + if (jl_is_typevar(n) || jl_is_uniontype(jl_unwrap_unionall(n))) { // TODO: this is disabled due to #39698; it is also inconsistent // with other similar checks, where we usually only check substituted // values and not the bounds of variables. diff --git a/src/julia.h b/src/julia.h index 2c9be8ae1aa2a..7d34a465c0886 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1410,7 +1410,7 @@ JL_DLLEXPORT int jl_type_equality_is_identity(jl_value_t *t1, jl_value_t *t2) JL JL_DLLEXPORT int jl_has_free_typevars(jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_has_typevar(jl_value_t *t, jl_tvar_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_has_typevar_from_unionall(jl_value_t *t, jl_unionall_t *ua); -JL_DLLEXPORT int jl_subtype_env_size(jl_value_t *t); +JL_DLLEXPORT int jl_subtype_env_size(jl_value_t *t) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, int envsz); JL_DLLEXPORT int jl_isa(jl_value_t *a, jl_value_t *t); JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b); diff --git a/src/subtype.c b/src/subtype.c index fbb1a74143cf9..809b0567a54b0 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -717,6 +717,8 @@ static jl_value_t *widen_Type(jl_value_t *t JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT // when a static parameter value is not known exactly. static jl_value_t *fix_inferred_var_bound(jl_tvar_t *var, jl_value_t *ty JL_MAYBE_UNROOTED) { + if (ty == NULL) // may happen if the user is intersecting with an incomplete type + return (jl_value_t*)var; if (!jl_is_typevar(ty) && jl_has_free_typevars(ty)) { jl_value_t *ans = ty; jl_array_t *vs = NULL; @@ -849,7 +851,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 if (oldval && !jl_egal(oldval, val)) e->envout[e->envidx] = (jl_value_t*)u->var; else - e->envout[e->envidx] = fix_inferred_var_bound(u->var, val); + e->envout[e->envidx] = val; // TODO: substitute the value (if any) of this variable into previous envout entries } @@ -1897,6 +1899,16 @@ JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, if (obvious_subtype == 0 || (obvious_subtype == 1 && envsz == 0)) subtype = obvious_subtype; // this ensures that running in a debugger doesn't change the result #endif + if (env) { + jl_unionall_t *ub = (jl_unionall_t*)y; + int i; + for (i = 0; i < envsz; i++) { + assert(jl_is_unionall(ub)); + jl_tvar_t *var = ub->var; + env[i] = fix_inferred_var_bound(var, env[i]); + ub = (jl_unionall_t*)ub->body; + } + } return subtype; } @@ -2634,7 +2646,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind if (!varval || (!is_leaf_bound(varval) && !vb->occurs_inv)) e->envout[e->envidx] = (jl_value_t*)vb->var; else if (!(oldval && jl_is_typevar(oldval) && jl_is_long(varval))) - e->envout[e->envidx] = fix_inferred_var_bound(vb->var, varval); + e->envout[e->envidx] = varval; } JL_GC_POP(); @@ -3595,17 +3607,11 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t * } if (penv) { jl_svec_t *e = jl_alloc_svec(sz); - *penv = e; - for (i = 0; i < sz; i++) - jl_svecset(e, i, env[i]); - jl_unionall_t *ub = (jl_unionall_t*)b; for (i = 0; i < sz; i++) { - assert(jl_is_unionall(ub)); - // TODO: assert(env[i] != NULL); - if (env[i] == NULL) - env[i] = (jl_value_t*)ub->var; - ub = (jl_unionall_t*)ub->body; + assert(env[i]); + jl_svecset(e, i, env[i]); } + *penv = e; } bot: JL_GC_POP(); @@ -3646,17 +3652,11 @@ int jl_subtype_matching(jl_value_t *a, jl_value_t *b, jl_svec_t **penv) // copy env to svec for return int i = 0; jl_svec_t *e = jl_alloc_svec(szb); - *penv = e; - for (i = 0; i < szb; i++) - jl_svecset(e, i, env[i]); - jl_unionall_t *ub = (jl_unionall_t*)b; for (i = 0; i < szb; i++) { - assert(jl_is_unionall(ub)); - // TODO: assert(env[i] != NULL); - if (env[i] == NULL) - env[i] = (jl_value_t*)ub->var; - ub = (jl_unionall_t*)ub->body; + assert(env[i]); + jl_svecset(e, i, env[i]); } + *penv = e; } JL_GC_POP(); return sub;