From f69b05704a1bd720e995386f5fa0344386e4a643 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Tue, 27 Aug 2019 02:32:19 -0500 Subject: [PATCH] error instead of widening index types in sparse (#33083) Followup to https://github.com/JuliaLang/julia/pull/31724/files#r317686891; instead of widening the index type dynamically based upon the index vector length, just throw an error in the case where the index type cannot hold all the indices in a CSC format. This previously was an OOB access (and likely segfault) in 1.2, so throwing an error here is not a breaking change -- and throwing an error restores type stability, addressing the performance regression flagged in #32985. (cherry picked from commit 9725fb4c3f94ecf4f2264f2bcceb636562f17006) --- stdlib/SparseArrays/src/sparsematrix.jl | 9 ++++----- stdlib/SparseArrays/test/sparse.jl | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index a40d0e68f0cce..5fbf25fa8f344 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -630,9 +630,8 @@ function sparse(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{ "length(I) (=$(length(I))) == length(J) (= $(length(J))) == length(V) (= ", "$(length(V)))"))) end - Tj = Ti - while isbitstype(Tj) && coolen >= typemax(Tj) - Tj = widen(Tj) + if Base.hastypemax(Ti) && coolen >= typemax(Ti) + throw(ArgumentError("the index type $Ti cannot hold $coolen elements; use a larger index type")) end if m == 0 || n == 0 || coolen == 0 if coolen != 0 @@ -645,13 +644,13 @@ function sparse(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{ SparseMatrixCSC(m, n, fill(one(Ti), n+1), Vector{Ti}(), Vector{Tv}()) else # Allocate storage for CSR form - csrrowptr = Vector{Tj}(undef, m+1) + csrrowptr = Vector{Ti}(undef, m+1) csrcolval = Vector{Ti}(undef, coolen) csrnzval = Vector{Tv}(undef, coolen) # Allocate storage for the CSC form's column pointers and a necessary workspace csccolptr = Vector{Ti}(undef, n+1) - klasttouch = Vector{Tj}(undef, n) + klasttouch = Vector{Ti}(undef, n) # Allocate empty arrays for the CSC form's row and nonzero value arrays # The parent method called below automagically resizes these arrays diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index a3acbd3cdd411..138eec975fe10 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2662,14 +2662,14 @@ end J1 = Int8.(rand(1:10, 500)) V1 = ones(500) # m * n < typemax(Ti) and length(I) >= typemax(Ti) - combining values - @test sparse(I1, J1, V1, 10, 10) !== nothing + @test_throws ArgumentError sparse(I1, J1, V1, 10, 10) # m * n >= typemax(Ti) and length(I) >= typemax(Ti) - @test sparse(I1, J1, V1, 12, 13) !== nothing + @test_throws ArgumentError sparse(I1, J1, V1, 12, 13) I1 = Int8.(rand(1:10, 126)) J1 = Int8.(rand(1:10, 126)) V1 = ones(126) # m * n >= typemax(Ti) and length(I) < typemax(Ti) - @test sparse(I1, J1, V1, 100, 100) !== nothing + @test size(sparse(I1, J1, V1, 100, 100)) == (100,100) end @testset "Typecheck too strict #31435" begin