Overload x[0:0.5:0.5] .= 1 when x is not AbstractVector

I have a custom type QuasiArray that implements broadcasting, and expected

x[0:0.5:0.5] .= 1

to lower to the functioning

view(x,0:0.5:0.5) .= 1

Unfortunately this is not working as expected, and x[0:0.5:0.5] .= 1 appears to be lowering to

broadcast!(identity, x[0:0.5:0.5], 1)

which does not modify x in place.

Is there some other overload needed?

I’d guess you need to overload Base.dotview:

julia> using Base.Meta

julia> Meta.lower(Main, :(x[0:0.5:0.5] .= 1))
:($(Expr(:thunk, CodeInfo(
1 ─ %1 = 0:0.5:0.5
β”‚   %2 = (Base.dotview)(x, %1)
β”‚   %3 = (Base.broadcasted)(Base.identity, 1)
β”‚   %4 = (Base.materialize!)(%2, %3)
└──      return %4
))))

Then considering the default methods available for dotview:

julia> methods(Base.dotview)
# 2 methods for generic function "dotview":
[1] dotview(B::BitArray, i::BitArray) in Base.Broadcast at broadcast.jl:1037
[2] dotview(args...) in Base.Broadcast at broadcast.jl:1067

julia> @edit Base.dotview(Float64[])

there’s a comment on the catch-all definition saying:

# x[...] .= f.(y...) ---> broadcast!(f, dotview(x, ...), y...).
# The dotview function defaults to getindex, but we override it in
# a few cases to get the expected in-place behavior without affecting
# explicit calls to view.   (All of this can go away if slices
# are changed to generate views by default.)

Base.@propagate_inbounds dotview(args...) = Base.maybeview(args...)
1 Like