Skip to content

Commit 3d1886f

Browse files
authored
Fix hash(::AbstractArray) failure in when some types support - and others do not (#25250)
The existing code only checked that subtraction was supported for the first two elements, but not for subsequent elements, which is necessary for heterogeneous arrays. Also fix a StackOverflow error due to the widen() fallback calling itself recursively by throwing a MethodError manually.
1 parent d7a5569 commit 3d1886f

File tree

4 files changed

+7
-0
lines changed

4 files changed

+7
-0
lines changed

base/abstractarray.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,7 @@ function hash(a::AbstractArray{T}, h::UInt) where T
19951995
# If true, wraparound overflow happened
19961996
sign(step) == cmp(x2, x1) || break
19971997
else
1998+
applicable(-, x2, x1) || break
19981999
# widen() is here to ensure no overflow can happen
19992000
step = widen(x2) - widen(x1)
20002001
end

base/operators.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ julia> widen(1.5f0)
787787
```
788788
"""
789789
widen(x::T) where {T} = convert(widen(T), x)
790+
widen(x::Type{T}) where {T} = throw(MethodError(widen, (T,)))
790791

791792
# function pipelining
792793

test/hashing.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ vals = Any[
7070
Any[Int8(127), Int8(-128), -383], 127:-255:-383,
7171
# Loss of precision with Float64
7272
Any[-2^53-1, 0.0, 2^53+1], [-2^53-1, 0, 2^53+1], (-2^53-1):2^53+1:(2^53+1),
73+
# Some combinations of elements support -, others do not
74+
[1, 2, "a"], [1, "a", 2], [1, 2, "a", 2], [1, 'a', 2],
7375
Set([1,2,3,4]),
7476
Set([1:10;]), # these lead to different key orders
7577
Set([7,9,4,10,2,3,5,8,6,1]), #

test/numbers.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,9 @@ end
24202420
@test typeof(widemul(UInt64(1),Int64(1))) == Int128
24212421
@test typeof(widemul(Int128(1),UInt128(1))) == BigInt
24222422
@test typeof(widemul(UInt128(1),Int128(1))) == BigInt
2423+
2424+
# Check that the widen() fallback doesn't trigger a StackOverflowError
2425+
@test_throws MethodError widen(String)
24232426
end
24242427
@testset ".//" begin
24252428
@test [1,2,3] // 4 == [1//4, 2//4, 3//4]

0 commit comments

Comments
 (0)