Skip to content
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

combine reduce_empty methods for Union{} eltypes #51948

Merged
merged 1 commit into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ function showerror(io::IO, ex::MethodError)
return showerror_ambiguous(io, meth, f, arg_types)
end
arg_types_param::SimpleVector = arg_types.parameters
show_candidates = true
print(io, "MethodError: ")
ft = typeof(f)
f_is_function = false
Expand All @@ -270,9 +269,6 @@ function showerror(io::IO, ex::MethodError)
if f === Base.convert && length(arg_types_param) == 2 && !is_arg_types
f_is_function = true
show_convert_error(io, ex, arg_types_param)
elseif f === mapreduce_empty || f === reduce_empty
print(io, "reducing over an empty collection is not allowed; consider supplying `init` to the reducer")
show_candidates = false
elseif isempty(methods(f)) && isa(f, DataType) && isabstracttype(f)
print(io, "no constructors have been defined for ", f)
elseif isempty(methods(f)) && !isa(f, Function) && !isa(f, Type)
Expand Down Expand Up @@ -346,11 +342,12 @@ function showerror(io::IO, ex::MethodError)
end
end
Experimental.show_error_hints(io, ex, arg_types_param, kwargs)
show_candidates && try
try
show_method_candidates(io, ex, kwargs)
catch ex
@error "Error showing method candidates, aborted" exception=ex,catch_backtrace()
end
nothing
end

striptype(::Type{T}) where {T} = T
Expand Down
17 changes: 7 additions & 10 deletions base/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,11 @@ pairwise_blocksize(::typeof(abs2), ::typeof(+)) = 4096


# handling empty arrays
_empty_reduce_error() = throw(ArgumentError("reducing over an empty collection is not allowed"))
_empty_reduce_error(@nospecialize(f), @nospecialize(T::Type)) = throw(ArgumentError("""
reducing with $f over an empty collection of element type $T is not allowed.
You may be able to prevent this error by supplying an `init` value to the reducer."""))
_empty_reduce_error() = throw(ArgumentError("reducing over an empty collection is not allowed; consider supplying `init` to the reducer"))
reduce_empty(f, T) = _empty_reduce_error()
mapreduce_empty(f, op, T) = _empty_reduce_error()
reduce_empty(f, ::Type{Union{}}, splat...) = _empty_reduce_error()
mapreduce_empty(f, op, ::Type{Union{}}, splat...) = _empty_reduce_error()

"""
Base.reduce_empty(op, T)
Expand All @@ -339,20 +340,16 @@ is generally ambiguous, and especially so when the element type is unknown).
As an alternative, consider supplying an `init` value to the reducer.
"""
reduce_empty(::typeof(+), ::Type{Union{}}) = _empty_reduce_error(+, Union{})
reduce_empty(::typeof(+), ::Type{T}) where {T} = zero(T)
reduce_empty(::typeof(+), ::Type{Bool}) = zero(Int)
reduce_empty(::typeof(*), ::Type{Union{}}) = _empty_reduce_error(*, Union{})
reduce_empty(::typeof(*), ::Type{T}) where {T} = one(T)
reduce_empty(::typeof(*), ::Type{<:AbstractChar}) = ""
reduce_empty(::typeof(&), ::Type{Bool}) = true
reduce_empty(::typeof(|), ::Type{Bool}) = false

reduce_empty(::typeof(add_sum), ::Type{Union{}}) = _empty_reduce_error(add_sum, Union{})
reduce_empty(::typeof(add_sum), ::Type{T}) where {T} = reduce_empty(+, T)
reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:SmallSigned} = zero(Int)
reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:SmallUnsigned} = zero(UInt)
reduce_empty(::typeof(mul_prod), ::Type{Union{}}) = _empty_reduce_error(mul_prod, Union{})
reduce_empty(::typeof(mul_prod), ::Type{T}) where {T} = reduce_empty(*, T)
reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallSigned} = one(Int)
reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallUnsigned} = one(UInt)
Expand Down Expand Up @@ -753,7 +750,7 @@ julia> maximum([1,2,3])
3
julia> maximum(())
ERROR: MethodError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer
ERROR: ArgumentError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer
Stacktrace:
[...]
Expand Down Expand Up @@ -785,7 +782,7 @@ julia> minimum([1,2,3])
1
julia> minimum([])
ERROR: MethodError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer
ERROR: ArgumentError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer
Stacktrace:
[...]
Expand Down
12 changes: 5 additions & 7 deletions test/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ end
@test reduce(max, [8 6 7 5 3 0 9]) == 9
@test reduce(+, 1:5; init=1000) == (1000 + 1 + 2 + 3 + 4 + 5)
@test reduce(+, 1) == 1
@test_throws "reducing with * over an empty collection of element type Union{} is not allowed" reduce(*, ())
@test_throws "reducing with * over an empty collection of element type Union{} is not allowed" reduce(*, Union{}[])
@test_throws "reducing over an empty collection is not allowed" reduce(*, ())
@test_throws "reducing over an empty collection is not allowed" reduce(*, Union{}[])

# mapreduce
@test mapreduce(-, +, [-10 -9 -3]) == ((10 + 9) + 3)
Expand Down Expand Up @@ -91,8 +91,7 @@ end
@test mapreduce(abs2, *, Float64[]) === 1.0
@test mapreduce(abs2, max, Float64[]) === 0.0
@test mapreduce(abs, max, Float64[]) === 0.0
@test_throws ["reducing over an empty collection is not allowed",
"consider supplying `init`"] mapreduce(abs2, &, Float64[])
@test_throws "reducing over an empty collection is not allowed" mapreduce(abs2, &, Float64[])
@test_throws str -> !occursin("Closest candidates are", str) mapreduce(abs2, &, Float64[])
@test_throws "reducing over an empty collection is not allowed" mapreduce(abs2, |, Float64[])

Expand Down Expand Up @@ -144,9 +143,8 @@ fz = float(z)
@test sum(z) === 136
@test sum(fz) === 136.0

@test_throws "reducing with add_sum over an empty collection of element type Union{} is not allowed" sum(Union{}[])
@test_throws ["reducing over an empty collection is not allowed",
"consider supplying `init`"] sum(sin, Int[])
@test_throws "reducing over an empty collection is not allowed" sum(Union{}[])
@test_throws "reducing over an empty collection is not allowed" sum(sin, Int[])
@test sum(sin, 3) == sin(3.0)
@test sum(sin, [3]) == sin(3.0)
a = sum(sin, z)
Expand Down