Skip to content

Commit

Permalink
broadcasting now falls back to iteration (fixes #23197, fixes #23746)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbauman committed Aug 5, 2018
1 parent bf3d985 commit 8c5c8e6
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 14 deletions.
6 changes: 3 additions & 3 deletions base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -605,9 +605,9 @@ broadcastable(x::Union{Symbol,AbstractString,Function,UndefInitializer,Nothing,R
broadcastable(x::Ptr) = Ref{Ptr}(x) # Cannot use Ref(::Ptr) until ambiguous deprecation goes through
broadcastable(::Type{T}) where {T} = Ref{Type{T}}(T)
broadcastable(x::Union{AbstractArray,Number,Ref,Tuple,Broadcasted}) = x
# In the future, default to collecting arguments. TODO: uncomment once deprecations are removed
# broadcastable(x) = collect(x)
# broadcastable(::Union{AbstractDict, NamedTuple}) = error("intentionally unimplemented to allow development in 1.x")
# Default to collecting iterables — which will error for non-iterables
broadcastable(x) = collect(x)
broadcastable(::Union{AbstractDict, NamedTuple}) = throw(ArgumentError("broadcasting over dictionaries and `NamedTuple`s is reserved"))

## Computation of inferred result type, for empty and concretely inferred cases only
_broadcast_getindex_eltype(bc::Broadcasted) = Base._return_type(bc.f, eltypes(bc.args))
Expand Down
11 changes: 0 additions & 11 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -575,17 +575,6 @@ function toc()
return t
end

# Broadcast no longer defaults to treating its arguments as scalar (#)
@noinline function Broadcast.broadcastable(x)
depwarn("""
broadcast will default to iterating over its arguments in the future. Wrap arguments of
type `x::$(typeof(x))` with `Ref(x)` to ensure they broadcast as "scalar" elements.
""", (:broadcast, :broadcast!))
return Ref{typeof(x)}(x)
end
@eval Base.Broadcast Base.@deprecate_binding Scalar DefaultArrayStyle{0} false
# After deprecation is removed, enable the fallback broadcastable definitions in base/broadcast.jl

# deprecate BitArray{...}(shape...) constructors to BitArray{...}(undef, shape...) equivalents
@deprecate BitArray{N}(dims::Vararg{Int,N}) where {N} BitArray{N}(undef, dims)
@deprecate BitArray(dims::NTuple{N,Int}) where {N} BitArray(undef, dims...)
Expand Down
6 changes: 6 additions & 0 deletions stdlib/LinearAlgebra/test/uniformscaling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,10 @@ end
@test (I - LL')\[[0], [0], [1]] == (I - LL)'\[[0], [0], [1]] == fill([1], 3)
end

# Ensure broadcasting of I is an error (could be made to work in the future)
@testset "broadcasting of I (#23197)" begin
@test_throws MethodError I .+ 1
@test_throws MethodError I .+ [1 1; 1 1]
end

end # module TestUniformscaling
12 changes: 12 additions & 0 deletions test/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,18 @@ end
@test broadcast(==, 1, AbstractArray) == false
end

@testset "broadcasting falls back to iteration (issues #26421, #19577, #23746)" begin
@test_throws ArgumentError broadcast(identity, Dict(1=>2))
@test_throws ArgumentError broadcast(identity, (a=1, b=2))
@test_throws ArgumentError length.(Dict(1 => IntSet(1:2), 2 => IntSet(1:3)))
@test_throws MethodError broadcast(identity, Base)

@test broadcast(identity, Iterators.filter(iseven, 1:10)) == 2:2:10
d = Dict([1,2] => 1.1, [3,2] => 0.1)
@test length.(keys(d)) == [2,2]
@test Set(exp.(Set([1,2,3]))) == Set(exp.([1,2,3]))
end

# Test that broadcasting identity where the input and output Array shapes do not match
# yields the correct result, not merely a partial copy. See pull request #19895 for discussion.
let N = 5
Expand Down

0 comments on commit 8c5c8e6

Please sign in to comment.