Skip to content

Commit 39ecb93

Browse files
vtjnashKristofferC
authored andcommitted
gf: avoid adding cache entries wider than the original method (#39140)
Sometimes we want to widen the compilation signature, but then end up with something which does not fit the original pattern. This then can cause problems later, when we try to use the Method (from the cache), but discover it does not actually match the call. Fixes #38999 (cherry picked from commit 8937f7e)
1 parent 40a2819 commit 39ecb93

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

src/gf.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ static void jl_compilation_sig(
646646
else if (jl_is_type_type(elt)) { // elt isa Type{T}
647647
if (very_general_type(decl_i)) {
648648
/*
649-
here's a fairly simple heuristic: if this argument slot's
649+
Here's a fairly simple heuristic: if this argument slot's
650650
declared type is general (Type or Any),
651651
then don't specialize for every Type that got passed.
652652
@@ -661,8 +661,9 @@ static void jl_compilation_sig(
661661
x::TypeConstructor matches the first but not the second, while
662662
also matching all other TypeConstructors. This means neither
663663
Type{TC} nor TypeConstructor is more specific.
664+
665+
But don't apply this heuristic if the argument is called (issue #36783).
664666
*/
665-
// don't apply this heuristic if the argument is called (issue #36783)
666667
int iscalled = i_arg > 0 && i_arg <= 8 && (definition->called & (1 << (i_arg - 1)));
667668
if (!iscalled) {
668669
if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
@@ -672,13 +673,13 @@ static void jl_compilation_sig(
672673
else if (jl_is_type_type(jl_tparam0(elt)) &&
673674
// try to give up on specializing type parameters for Type{Type{Type{...}}}
674675
(jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_free_typevars(decl_i))) {
675-
// TODO: this is probably solidly unsound and would corrupt the cache in many cases
676676
/*
677677
actual argument was Type{...}, we computed its type as
678-
Type{Type{...}}. we must avoid unbounded nesting here, so
679-
cache the signature as Type{T}, unless something more
680-
specific like Type{Type{Int32}} was actually declared.
681-
this can be determined using a type intersection.
678+
Type{Type{...}}. we like to avoid unbounded nesting here, so
679+
compile (and hopefully cache) the signature as Type{T},
680+
unless something more specific like Type{Type{Int32}} was
681+
actually declared. this can be determined using a type
682+
intersection.
682683
*/
683684
if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
684685
if (i < nargs || !definition->isva) {
@@ -1017,12 +1018,12 @@ static jl_method_instance_t *cache_method(
10171018
intptr_t nspec = (mt == NULL || mt == jl_type_type_mt || mt == jl_nonfunction_mt ? definition->nargs + 1 : mt->max_args + 2);
10181019
jl_compilation_sig(tt, sparams, definition, nspec, &newparams);
10191020
if (newparams) {
1020-
cache_with_orig = 0;
10211021
compilationsig = jl_apply_tuple_type(newparams);
10221022
temp2 = (jl_value_t*)compilationsig;
10231023
// In most cases `!jl_isa_compileable_sig(tt, definition))`,
10241024
// although for some cases, (notably Varargs)
10251025
// we might choose a replacement type that's preferable but not strictly better
1026+
cache_with_orig = !jl_subtype(compilationsig, definition->sig);
10261027
}
10271028
// TODO: maybe assert(jl_isa_compileable_sig(compilationsig, definition));
10281029
newmeth = jl_specializations_get_linfo(definition, (jl_value_t*)compilationsig, sparams);
@@ -1031,7 +1032,6 @@ static jl_method_instance_t *cache_method(
10311032
jl_svec_t* guardsigs = jl_emptysvec;
10321033
if (!cache_with_orig && mt) {
10331034
// now examine what will happen if we chose to use this sig in the cache
1034-
// TODO: should we first check `compilationsig <: definition`?
10351035
size_t min_valid2 = 1;
10361036
size_t max_valid2 = ~(size_t)0;
10371037
temp = ml_matches(mt, 0, compilationsig, MAX_UNSPECIALIZED_CONFLICTS, 1, 1, world, 0, &min_valid2, &max_valid2, NULL);

0 commit comments

Comments
 (0)