Repository: invenia/NamedDims.jl (julia)

Issue:
Broadcasting assignment `.=` is broken for `NamedDimsArray`s
Compare dense arrays and `NamedDimsArrays`:

```julia
julia> rand(5, 2) .= rand(5, 1)
5×2 Matrix{Float64}:
 0.299664  0.299664
 0.981362  0.981362
 0.703687  0.703687
 0.591929  0.591929
 0.754977  0.754977

julia> NamedDimsArray{(:a, :b)}(rand(5, 2)) .= NamedDimsArray{(:a, :b)}(rand(5, 1))
ERROR: DimensionMismatch("destination axes (Base.OneTo(5), Base.OneTo(2)) are not compatible with source axes (Base.OneTo(5), Base.OneTo(1))")
Stacktrace:
 [1] throwdm(axdest::Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, axsrc::Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}})
   @ Base.Broadcast ./broadcast.jl:1060
 [2] copyto!
   @ ./broadcast.jl:972 [inlined]
 [3] copyto!
   @ ./broadcast.jl:936 [inlined]
 [4] copyto!(dest::NamedDimsArray{(:a, :b), Float64, 2, Matrix{Float64}}, bc::Base.Broadcast.Broadcasted{NamedDims.NamedDimsStyle{Base.Broadcast.DefaultArrayStyle{2}}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, typeof(identity), Tuple{NamedDimsArray{(:a, :b), Float64, 2, Matrix{Float64}}}})
   @ NamedDims ~/JuliaEnvs/PortfolioNets.jl/dev/NamedDims/src/broadcasting.jl:70
 [5] materialize!
   @ ./broadcast.jl:894 [inlined]
 [6] materialize!(dest::NamedDimsArray{(:a, :b), Float64, 2, Matrix{Float64}}, bc::Base.Broadcast.Broadcasted{NamedDims.NamedDimsStyle{Base.Broadcast.DefaultArrayStyle{2}}, Nothing, typeof(identity), Tuple{NamedDimsArray{(:a, :b), Float64, 2, Matrix{Float64}}}})
   @ Base.Broadcast ./broadcast.jl:891
 [7] top-level scope
   @ REPL[27]:1
```

Pull request:
Closes #175.

Wow, this took me a while (hard to debug base functions), and I still don't understand how broadcasting works. The issue was that when the inner broadcasting style was extracted, the axes were not updated to the axes that `instantiate` returns for the outer style.

Patch:
diff --git a/Project.toml b/Project.toml
index 03e2990..c3c991f 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
 name = "NamedDims"
 uuid = "356022a1-0364-5f58-8944-0da4b18d706f"
 authors = ["Invenia Technical Computing Corporation"]
-version = "0.2.36"
+version = "0.2.37"
 
 [deps]
 AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
diff --git a/src/broadcasting.jl b/src/broadcasting.jl
index c894f45..bfa98bb 100644
--- a/src/broadcasting.jl
+++ b/src/broadcasting.jl
@@ -50,7 +50,7 @@ and `NamedDimsStyle` with the wrapped `BroadcastStyle`.
 """
 function unwrap_broadcasted(bc::Broadcasted{NamedDimsStyle{S}}) where {S}
     inner_args = map(unwrap_broadcasted, bc.args)
-    return Broadcasted{S}(bc.f, inner_args)
+    return Broadcasted{S}(bc.f, inner_args, axes(bc))
 end
 unwrap_broadcasted(x) = x
 unwrap_broadcasted(nda::NamedDimsArray) = parent(nda)


Test patch:
diff --git a/test/broadcasting.jl b/test/broadcasting.jl
index 754065f..5b2d135 100644
--- a/test/broadcasting.jl
+++ b/test/broadcasting.jl
@@ -114,8 +114,12 @@ using Tracker
 
         @test dimnames(z .= ab .+ a_) == (:a, :b)
         @test dimnames(a_ .= ba' .+ ab) == (:a, :b)
-    end
 
+        # https://github.com/invenia/NamedDims.jl/issues/175
+        nda1 = NamedDimsArray(zeros(2, 2), (:a, :b))
+        nda2 = NamedDimsArray([1.0 2.0;], (:a, :b))
+        @test (nda1 .= nda2) == (parent(nda1) .= parent(nda2))
+    end
 end
 
 @testset "Competing Wrappers" begin