Skip to content

Commit

Permalink
gf: invalidate when adding new methods (#39343)
Browse files Browse the repository at this point in the history
Error introduced by #36733

Fixes #38435
  • Loading branch information
vtjnash authored Jan 25, 2021
1 parent fd8f97e commit cdaf740
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
34 changes: 23 additions & 11 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1666,21 +1666,33 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
size_t ins = 0;
for (i = 1; i < na; i += 2) {
jl_value_t *backedgetyp = backedges[i - 1];
int missing = 0;
if (jl_type_intersection2(backedgetyp, (jl_value_t*)type, &isect, &isect2)) {
// see if the intersection was actually already fully
// covered by anything (method or ambiguity is okay)
// See if the intersection was actually already fully
// covered, but that the new method is ambiguous.
// -> no previous method: now there is one, need to update the missing edge
// -> one+ previously matching method(s):
// -> more specific then all of them: need to update the missing edge
// -> some may have been ambiguous: now there is a replacement
// -> some may have been called: now there is a replacement (also will be detected in the loop later)
// -> less specific or ambiguous with any one of them: can ignore the missing edge (not missing)
// -> some may have been ambiguous: still are
// -> some may have been called: they may be partly replaced (will be detected in the loop later)
missing = 1;
size_t j;
for (j = 0; j < n; j++) {
jl_method_t *m = d[j];
if (jl_subtype(isect, m->sig))
break;
if (isect2 && jl_subtype(isect2, m->sig))
break;
if (jl_subtype(isect, m->sig) || (isect2 && jl_subtype(isect2, m->sig))) {
// We now know that there actually was a previous
// method for this part of the type intersection.
if (!jl_type_morespecific(type, m->sig)) {
missing = 0;
break;
}
}
}
if (j != n)
isect = jl_bottom_type;
}
if (isect != jl_bottom_type) {
if (missing) {
jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i];
invalidate_external(backedge, max_world);
invalidate_method_instance(backedge, max_world, 0);
Expand Down Expand Up @@ -1722,7 +1734,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
isect3 = jl_type_intersection(m->sig, (jl_value_t*)mi->specTypes);
if (jl_type_intersection2(type, isect3, &isect, &isect2)) {
if (morespec[j] == (char)morespec_unknown)
morespec[j] = (char)jl_type_morespecific(m->sig, type) ? morespec_is : morespec_isnot;
morespec[j] = (char)(jl_type_morespecific(m->sig, type) ? morespec_is : morespec_isnot);
if (morespec[j] == (char)morespec_is)
// not actually shadowing--the existing method is still better
break;
Expand All @@ -1737,7 +1749,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
if (m == m2 || !(jl_subtype(isect, m2->sig) || (isect && jl_subtype(isect, m2->sig))))
continue;
if (morespec[k] == (char)morespec_unknown)
morespec[k] = (char)jl_type_morespecific(m2->sig, type) ? morespec_is : morespec_isnot;
morespec[k] = (char)(jl_type_morespecific(m2->sig, type) ? morespec_is : morespec_isnot);
if (morespec[k] == (char)morespec_is)
// not actually shadowing this--m2 will still be better
break;
Expand Down
8 changes: 8 additions & 0 deletions test/worlds.jl
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ notify(c26506_1)
wait(c26506_2)
@test result26506[1] == 3

# issue #38435
f38435(::Int, ::Any) = 1
f38435(::Any, ::Int) = 2
g38435(x) = f38435(x, x)
@test_throws MethodError(f38435, (1, 1), Base.get_world_counter()) g38435(1)
f38435(::Int, ::Int) = 3.0
@test g38435(1) === 3.0


## Invalidation tests

Expand Down

0 comments on commit cdaf740

Please sign in to comment.