Skip to content

Commit 5b18d5f

Browse files
JeffBezansonKristofferC
authored andcommitted
fix #30394, an unsoundness in ml_matches (#30396)
This fixes a corner case where a bug is caused, counter-intuitively, by an over-estimated intersection. We have method signatures A and B, with A<B (A is a strict subtype). We have a dispatch tuple X, where X<:B and !(X<:A). However, intersection returns X for intersect(X,A). Since there appears to be a match there and A<B, ml_matches skips the match with B. The fix just requires dispatch tuples to be a subtype of a signature in order to match at all. (cherry picked from commit b167bc2)
1 parent 6aaeac0 commit 5b18d5f

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

src/gf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2395,6 +2395,12 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio
23952395
closure->max_valid = ml->max_world;
23962396
}
23972397
}
2398+
// In some corner cases type intersection is conservative and returns something
2399+
// for intersect(A, B) even though A is a dispatch tuple and !(A <: B).
2400+
// For dispatch purposes in such a case we know there's no match. This check
2401+
// fixes issue #30394.
2402+
if (jl_is_dispatch_tupletype(closure->match.type) && !closure->match.issubty)
2403+
return 1;
23982404
// a method is shadowed if type <: S <: m->sig where S is the
23992405
// signature of another applicable method
24002406
/*

test/compiler/compiler.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,3 +2077,24 @@ function f29036(s, i)
20772077
val
20782078
end
20792079
@test Base.return_types(f29036, (String, Int)) == Any[Char]
2080+
2081+
# issue #30394
2082+
mutable struct Base30394
2083+
a::Int
2084+
end
2085+
2086+
mutable struct Foo30394
2087+
foo_inner::Base30394
2088+
Foo30394() = new(Base30394(1))
2089+
end
2090+
2091+
mutable struct Foo30394_2
2092+
foo_inner::Foo30394
2093+
Foo30394_2() = new(Foo30394())
2094+
end
2095+
2096+
f30394(foo::T1, ::Type{T2}) where {T2, T1 <: T2} = foo
2097+
2098+
f30394(foo, T2) = f30394(foo.foo_inner, T2)
2099+
2100+
@test Base.return_types(f30394, (Foo30394_2, Type{Base30394})) == Any[Base30394]

0 commit comments

Comments
 (0)