From 18d52fa38a31da9515bd5d000ab34830938d0e80 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 21 Nov 2018 22:09:39 -0800 Subject: [PATCH 1/3] Remove unused struct CapturedScalars --- stdlib/SparseArrays/src/higherorderfns.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/stdlib/SparseArrays/src/higherorderfns.jl b/stdlib/SparseArrays/src/higherorderfns.jl index e09ca104c4220..23d422349d620 100644 --- a/stdlib/SparseArrays/src/higherorderfns.jl +++ b/stdlib/SparseArrays/src/higherorderfns.jl @@ -1006,10 +1006,6 @@ end _copyto!(parevalf, dest, passedsrcargstup...) end -struct CapturedScalars{F, Args, Order} - args::Args -end - # capturescalars takes a function (f) and a tuple of mixed sparse vectors/matrices and # broadcast scalar arguments (mixedargs), and returns a function (parevalf, i.e. partially # evaluated f) and a reduced argument tuple (passedargstup) containing only the sparse From 3a63ca2aee6f27fd663f1c5b223f68abdb8b7cd3 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 21 Nov 2018 20:22:37 -0800 Subject: [PATCH 2/3] Fix method ambiguities in SparseArrays --- stdlib/SparseArrays/src/higherorderfns.jl | 7 ++++++- stdlib/SparseArrays/test/ambiguous_exec.jl | 4 ++++ stdlib/SparseArrays/test/higherorderfns.jl | 7 +++++++ stdlib/SparseArrays/test/sparse.jl | 8 ++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 stdlib/SparseArrays/test/ambiguous_exec.jl diff --git a/stdlib/SparseArrays/src/higherorderfns.jl b/stdlib/SparseArrays/src/higherorderfns.jl index 23d422349d620..dac19ef7a73f2 100644 --- a/stdlib/SparseArrays/src/higherorderfns.jl +++ b/stdlib/SparseArrays/src/higherorderfns.jl @@ -973,6 +973,7 @@ function _copy(f, args...) parevalf, passedargstup = capturescalars(f, args) return _copy(parevalf, passedargstup...) end +_copy(f) = throw(MethodError(_copy, (f))) # avoid method ambiguity function _shapecheckbc(f, args...) _aresameshape(args...) ? _noshapecheck_map(f, args...) : _diffshape_broadcast(f, args...) @@ -1020,9 +1021,13 @@ end # Work around losing Type{T}s as DataTypes within the tuple that makeargs creates @inline capturescalars(f, mixedargs::Tuple{Ref{Type{T}}, Vararg{Any}}) where {T} = capturescalars((args...)->f(T, args...), Base.tail(mixedargs)) +@inline capturescalars(f, mixedargs::Tuple{Ref{Type{T}}, Ref{Type{S}}, Vararg{Any}}) where {T, S} = + # This definition is identical to the one above and necessary only for + # avoiding method ambiguity. + capturescalars((args...)->f(T, args...), Base.tail(mixedargs)) @inline capturescalars(f, mixedargs::Tuple{SparseVecOrMat, Ref{Type{T}}, Vararg{Any}}) where {T} = capturescalars((a1, args...)->f(a1, T, args...), (mixedargs[1], Base.tail(Base.tail(mixedargs))...)) -@inline capturescalars(f, mixedargs::Tuple{Union{Ref,AbstractArray{0}}, Ref{Type{T}}, Vararg{Any}}) where {T} = +@inline capturescalars(f, mixedargs::Tuple{Union{Ref,AbstractArray{<:Any,0}}, Ref{Type{T}}, Vararg{Any}}) where {T} = capturescalars((args...)->f(mixedargs[1], T, args...), Base.tail(Base.tail(mixedargs))) nonscalararg(::SparseVecOrMat) = true diff --git a/stdlib/SparseArrays/test/ambiguous_exec.jl b/stdlib/SparseArrays/test/ambiguous_exec.jl new file mode 100644 index 0000000000000..a466f2534794a --- /dev/null +++ b/stdlib/SparseArrays/test/ambiguous_exec.jl @@ -0,0 +1,4 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +using Test, SparseArrays +@test detect_ambiguities(SparseArrays; imported=true, recursive=true) == [] diff --git a/stdlib/SparseArrays/test/higherorderfns.jl b/stdlib/SparseArrays/test/higherorderfns.jl index 5871e2d96e1e2..cdd3633febb86 100644 --- a/stdlib/SparseArrays/test/higherorderfns.jl +++ b/stdlib/SparseArrays/test/higherorderfns.jl @@ -632,4 +632,11 @@ end @test minimum(sparse([1, 2], [1, 2], ones(Int32, 2)), dims = 1) isa Matrix end +@testset "Issue #30118" begin + @test ((_, x) -> x).(Int, spzeros(3)) == spzeros(3) + @test ((_, _, x) -> x).(Int, Int, spzeros(3)) == spzeros(3) + @test ((_, _, _, x) -> x).(Int, Int, Int, spzeros(3)) == spzeros(3) + @test_broken ((_, _, _, _, x) -> x).(Int, Int, Int, Int, spzeros(3)) == spzeros(3) +end + end # module diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 6e30ab62bd5a1..3fa2c87fa8099 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2343,4 +2343,12 @@ end @test_throws MethodError sprandn(T, 5, 5, 0.5) end +@testset "method ambiguity" begin + # Ambiguity test is run inside a clean process. + # https://github.com/JuliaLang/julia/issues/28804 + script = joinpath(@__DIR__, "ambiguous_exec.jl") + cmd = `$(Base.julia_cmd()) --startup-file=no $script` + @test success(pipeline(cmd; stdout=stdout, stderr=stderr)) +end + end # module From 5bbbf65129db9d5f3e045bb76fe901f897e6b6d1 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Thu, 22 Nov 2018 12:47:53 -0800 Subject: [PATCH 3/3] Fix HigherOrderFns._copy(f) --- stdlib/SparseArrays/src/higherorderfns.jl | 2 +- stdlib/SparseArrays/test/higherorderfns.jl | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/src/higherorderfns.jl b/stdlib/SparseArrays/src/higherorderfns.jl index dac19ef7a73f2..63d318af434f9 100644 --- a/stdlib/SparseArrays/src/higherorderfns.jl +++ b/stdlib/SparseArrays/src/higherorderfns.jl @@ -973,7 +973,7 @@ function _copy(f, args...) parevalf, passedargstup = capturescalars(f, args) return _copy(parevalf, passedargstup...) end -_copy(f) = throw(MethodError(_copy, (f))) # avoid method ambiguity +_copy(f) = throw(MethodError(_copy, (f,))) # avoid method ambiguity function _shapecheckbc(f, args...) _aresameshape(args...) ? _noshapecheck_map(f, args...) : _diffshape_broadcast(f, args...) diff --git a/stdlib/SparseArrays/test/higherorderfns.jl b/stdlib/SparseArrays/test/higherorderfns.jl index cdd3633febb86..5b1423582f0d5 100644 --- a/stdlib/SparseArrays/test/higherorderfns.jl +++ b/stdlib/SparseArrays/test/higherorderfns.jl @@ -639,4 +639,21 @@ end @test_broken ((_, _, _, _, x) -> x).(Int, Int, Int, Int, spzeros(3)) == spzeros(3) end +using SparseArrays.HigherOrderFns: SparseVecStyle + +@testset "Issue #30120: method ambiguity" begin + # HigherOrderFns._copy(f) was ambiguous. It may be impossible to + # invoke this from dot notation and it is an error anyway. But + # when someone invokes it by accident, we want it to produce a + # meaningful error. + err = try + copy(Broadcast.Broadcasted{SparseVecStyle}(rand, ())) + catch err + err + end + @test err isa MethodError + @test !occursin("is ambiguous", sprint(showerror, err)) + @test occursin("no method matching _copy(::typeof(rand))", sprint(showerror, err)) +end + end # module