Skip to content

Commit 8937f7e

Browse files
authored
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
1 parent ca07546 commit 8937f7e

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
@@ -650,7 +650,7 @@ static void jl_compilation_sig(
650650
else if (jl_is_type_type(elt)) { // elt isa Type{T}
651651
if (very_general_type(decl_i)) {
652652
/*
653-
here's a fairly simple heuristic: if this argument slot's
653+
Here's a fairly simple heuristic: if this argument slot's
654654
declared type is general (Type or Any),
655655
then don't specialize for every Type that got passed.
656656
@@ -665,8 +665,9 @@ static void jl_compilation_sig(
665665
x::TypeConstructor matches the first but not the second, while
666666
also matching all other TypeConstructors. This means neither
667667
Type{TC} nor TypeConstructor is more specific.
668+
669+
But don't apply this heuristic if the argument is called (issue #36783).
668670
*/
669-
// don't apply this heuristic if the argument is called (issue #36783)
670671
int iscalled = i_arg > 0 && i_arg <= 8 && (definition->called & (1 << (i_arg - 1)));
671672
if (!iscalled) {
672673
if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
@@ -676,13 +677,13 @@ static void jl_compilation_sig(
676677
else if (jl_is_type_type(jl_tparam0(elt)) &&
677678
// try to give up on specializing type parameters for Type{Type{Type{...}}}
678679
(jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_free_typevars(decl_i))) {
679-
// TODO: this is probably solidly unsound and would corrupt the cache in many cases
680680
/*
681681
actual argument was Type{...}, we computed its type as
682-
Type{Type{...}}. we must avoid unbounded nesting here, so
683-
cache the signature as Type{T}, unless something more
684-
specific like Type{Type{Int32}} was actually declared.
685-
this can be determined using a type intersection.
682+
Type{Type{...}}. we like to avoid unbounded nesting here, so
683+
compile (and hopefully cache) the signature as Type{T},
684+
unless something more specific like Type{Type{Int32}} was
685+
actually declared. this can be determined using a type
686+
intersection.
686687
*/
687688
if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
688689
if (i < nargs || !definition->isva) {
@@ -1024,12 +1025,12 @@ static jl_method_instance_t *cache_method(
10241025
intptr_t nspec = (mt == NULL || mt == jl_type_type_mt || mt == jl_nonfunction_mt ? definition->nargs + 1 : mt->max_args + 2);
10251026
jl_compilation_sig(tt, sparams, definition, nspec, &newparams);
10261027
if (newparams) {
1027-
cache_with_orig = 0;
10281028
compilationsig = jl_apply_tuple_type(newparams);
10291029
temp2 = (jl_value_t*)compilationsig;
10301030
// In most cases `!jl_isa_compileable_sig(tt, definition))`,
10311031
// although for some cases, (notably Varargs)
10321032
// we might choose a replacement type that's preferable but not strictly better
1033+
cache_with_orig = !jl_subtype(compilationsig, definition->sig);
10331034
}
10341035
// TODO: maybe assert(jl_isa_compileable_sig(compilationsig, definition));
10351036
newmeth = jl_specializations_get_linfo(definition, (jl_value_t*)compilationsig, sparams);
@@ -1038,7 +1039,6 @@ static jl_method_instance_t *cache_method(
10381039
jl_svec_t* guardsigs = jl_emptysvec;
10391040
if (!cache_with_orig && mt) {
10401041
// now examine what will happen if we chose to use this sig in the cache
1041-
// TODO: should we first check `compilationsig <: definition`?
10421042
size_t min_valid2 = 1;
10431043
size_t max_valid2 = ~(size_t)0;
10441044
temp = ml_matches(mt, 0, compilationsig, MAX_UNSPECIALIZED_CONFLICTS, 1, 1, world, 0, &min_valid2, &max_valid2, NULL);

0 commit comments

Comments
 (0)