-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ml-matches: update and improve ambiguity computation #36962
Conversation
e556167
to
7e55d58
Compare
ambig = Set{Any}(((m1.sig, m2.sig) for (m1, m2) in ambig)) | ||
expect = [] | ||
|
||
Sys.iswindows() || push!(expect, (Tuple{typeof(\),Factorization{T},Union{Array{Complex{T},1}, Array{Complex{T},2}}} where T<:Union{Float32, Float64}, Tuple{typeof(\),LQ{TA,S} where S<:AbstractMatrix{TA},StridedVecOrMat{TB}} where TB where TA)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this one seems possibly more real though, as the intersection can be either:
julia> t = typeintersect(Tuple{typeof(\),Factorization{T},Union{Array{Complex{T},2}, Array{Complex{T},1}}} where T<:Union{Float32, Float64}, Tuple{typeof(\),LQ{TA,S} where S<:AbstractMatrix{TA},StridedVecOrMat{TB}} where TB where TA)
Tuple{typeof(\),
LQ{T,S} where S<:AbstractMatrix{T},
Union{Array{Complex{T},2}, Array{Complex{T},1}}} where T<:Union{Float32, Float64}
or
julia> t = typeintersect(Tuple{typeof(\),LQ{TA,S} where S<:AbstractMatrix{TA},StridedVecOrMat{TB}} where TB where TA, Tuple{typeof(\),Factorization{T},Union{Array{Complex{T},2}, Array{Complex{T},1}}} where T<:Union{Float32, Float64})
Tuple{typeof(\),
Union{LQ{TA,S} where S<:AbstractMatrix{TA}, LQ{TA1,S} where S<:AbstractMatrix{TA1}},
Union{Array{Complex{TA},1}, Array{Complex{TA1},2}}} where TA1<:Union{Float32, Float64} where TA<:Union{Float32, Float64}
which end up matching slightly different sets of methods:
1-element Vector{Any}:
Core.MethodMatch(Tuple{typeof(\),Union{LQ{T,S} where S<:AbstractMatrix{T}, LQ{T,S} where S<:AbstractMatrix{T}},Union{Array{Complex{T},2}, Array{Complex{T},1}}} where T<:Union{Float32, Float64}, svec(T<:Union{Float32, Float64}), \(F::LQ{T,S} where S<:AbstractMatrix{T}, B::Union{Array{Complex{T},1}, Array{Complex{T},2}}) where T<:Union{Float32, Float64} in LinearAlgebra at /data/vtjnash/julia/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/lq.jl:322, true)
vs
2-element Vector{Any}:
Core.MethodMatch(Tuple{typeof(\),LQ{T,S} where S<:AbstractMatrix{T},Union{Array{Complex{T},1}, Array{Complex{T},2}}} where T<:Union{Float32, Float64}, svec(T<:Union{Float32, Float64}), \(F::LQ{T,S} where S<:AbstractMatrix{T}, B::Union{Array{Complex{T},1}, Array{Complex{T},2}}) where T<:Union{Float32, Float64} in LinearAlgebra at /data/vtjnash/julia/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/lq.jl:322, false)
Core.MethodMatch(Tuple{typeof(\),Union{LQ{TA,S} where S<:AbstractMatrix{TA}, LQ{TA1,S} where S<:AbstractMatrix{TA1}},Union{Array{Complex{TA},1}, Array{Complex{TA1},2}}} where TA1<:Union{Float32, Float64} where TA<:Union{Float32, Float64}, svec(TA<:Union{Float32, Float64}, TB<:(Complex{TA} where TA<:Union{Float32, Float64})), \(A::LQ{TA,S} where S<:AbstractMatrix{TA}, B::StridedVecOrMat{TB}) where {TA, TB} in LinearAlgebra at /data/vtjnash/julia/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/lq.jl:310, true)
b70bcce
to
d83a051
Compare
d83a051
to
9ada1fc
Compare
more symmetry in use of type-intersection
9ada1fc
to
830eb8a
Compare
Sorry, I should have looked at this earlier. While you've carefully carved out exemptions for ambiguity tests that run within Julia itself, what should packages do? I have a lot of packages where the tests include I'm not arguing that the new algorithm is wrong (I haven't checked), but just wondering whether there's a plan for moving forward. |
There’s no reason anymore to include Base and Core in your list. List just the modules you care about. |
Is that true even if we add methods to functions owned by Base? I'll mimic the style of tests here. I am adding a "needs news" tag. |
# this is basically just a list of everything for which typeintersection is too conservative, | ||
# and ends up matching some methods that don't actually have an interesting intersection | ||
expect = [] | ||
push!(expect, (Tuple{typeof(convert),Type{T},Any} where T>:Union{Missing, Nothing}, Tuple{typeof(convert),Type{T},T} where T>:Nothing)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I try to understand this list of methods enumerated in the expect
vector. Since this PR is an improvement, they are previously false-negative and now true-positive, right? If so, is it correct to assume that I should be able to invoke a method error with some combination? However, I couldn't get the run-time ambiguity error with a few examples for this first item of expect
. What am I doing wrong here?
julia> VERSION
v"1.6.0-DEV.819"
julia> convert(Union{Missing, Nothing}, missing)
missing
julia> convert(Union{Missing, Nothing}, nothing)
julia> convert(Union{Missing, Nothing, Int}, missing)
missing
julia> convert(Union{Missing, Nothing, Int}, nothing)
julia> convert(Union{Missing, Nothing, Int}, 1)
1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessarily—the type system might claim that such an ambiguity exists, while no counterfactual actually does. I posted a link above that references this particular failure in the type system (#36951).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the API of detect_ambiguities
? I've been assuming that it returns a non-empty vector if and only if there exist concrete argument types that would cause a method error. Could you document the exact guarantee? For example, it would be helpful to document that the users should expect false positive or negative.
If providing a guarantee is not possible or not appropriate (e.g., to allow the type system to evolve), can we demote detect_ambiguities
(and detect_unbound_args
?) to experimental API and explicitly mention as such.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from problems with the type system, that is what this did before and is still what it does. Hence the new bug report number also. There was a bug in v1.0 where someone got a conditional backwards and accidentally additionally filtered out any ambiguity resulting from a failure of type-intersection. Hence this PR. That's now fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is what this did before and is still what it does
What is that? Could you explain what API detect_ambiguities
provides now? Could you clarify what kind of "bound" users can assume with respect to the run-time behavior (method error)? No false positive (which is apparently not the case from your previous comment?)? No false negative (i.e., if detect_ambiguities
returns an empty vector, there will be no method error; given there is no bug, of course)? Both kinds of failures are possible (i.e., it's just a hint)?
I noted above #36962 (comment), I think we need more documentation. So, I'm also adding I'm also adding
|
This seems to cause some significant latency regressions.
with this reverted:
So I don't think this change is worth it. |
Yeah, I don’t think inference should be asking us to do the more expensive query (eliminate ambiguous methods) that this makes even worse. Need to first get data on what patterns this is affecting. IIUC, this is revealing problems with type-intersection that are stealing away a lot of performance by making it slightly worse in those cases. |
(#32) * Do not hard-code default options for `Test.detect_ambiguities` * Ignore ambiguities from Base for now
Using commit: Workaround over-sensitive ambiguity detection from JuliaLang/julia#36962 (#32) JuliaTesting/Aqua.jl@fe03e3f
Using commit: Workaround over-sensitive ambiguity detection from JuliaLang/julia#36962 (#32) JuliaTesting/Aqua.jl@fe03e3f
(#419) * Update to JuliaTesting/Aqua.jl#32 * Don't call test_ambiguities with Base in julia >= 1.6.0-DEV.816
Wait until JuliaLang/julia#36962 shakes out
Wait until JuliaLang/julia#36962 shakes out
I'm not entirely sure from @vtjnash's response above what the future is likely to look like. Will this be reverted? Or will this be retained but fixed to address the performance issues Jeff noticed? The reason I ask is that tons of packages are facing ambiguity-related test failures, and I'm unsure whether to migrate to the new style (the right strategy if this is being kept) or keep the old (if this is being reverted). |
Ah, I see from #37458 (comment) that this seems likely to be reverted. |
This reverts commit 21ff6ee.
It should probably be surgically disabled again (as this code has been), rather than undoing the bug fixes entirely, but I can't get to that till next week. |
Removes a part of #36962 that was the source of major ire by several users: This restores some abort code paths that I had put in place to cause isambiguous to return incorrect answers in this particular case. Even though the underlying algorithm can now deal with these cases correctly, users were not pleased that the algorithm was now handling these cases correctly and attacked with gusto. Additionally, it fixes a performance bug in ml-matches, where I'd accidentally set two flags in the wrong direction, which were still conservatively correct, but prevented us from using the fast path.
Reporting ambiguities that cannot be fixed by the user since they are not part of the testtarget can be harmful to the user experience since they will never be useful, since at least JuliaLang/julia#36962. Fixes JuliaTesting#77
Reporting ambiguities that cannot be fixed by the user since they are not part of the testtarget can be harmful to the user experience since they will never be useful, since at least JuliaLang/julia#36962. --------- Co-authored-by: Lars Göttgens <lars.goettgens@rwth-aachen.de>
This uses the much-enhanced ambiguity computing algorithm in ml-matches, and implements this all better. The failures here are actually all type-intersection problems (#36951), as far as I can tell.