Closed
Description
The following code is valid in 1.10.x but errors in 1.11:
struct Thing
data::Float64
end
Base.zero(::Type{Thing}) = Thing(0.)
Base.zero(::Thing) = Thing(0.)
Base.one(::Type{Thing}) = Thing(1.)
Base.one(::Thing) = Thing(1.)
Base.:+(t::Thing...) = +(getfield.(t, :data)...)
Base.:*(t::Thing...) = *(getfield.(t, :data)...)
A = Thing.(randn(2,2))
A * A
The reason seems to be that A * A
uses the five-argument mul!
internally, which now performs a multiplication by alpha::Bool
instead of checking isone(alpha)
(https://github.com/JuliaLang/julia/pull/52038/files#diff-a454fe10464022052956170246cb4be7e2e71bc517e02c2ec0a9548fb6aaaf29R791).
Essentially:
- 1.10 only required the matrix elements to be a valid semiring, implementing
+
,*
,zero
,one
. - 1.11 requires that
A[i] * true
is valid code. While this might seem innocent at a first glance, it is not mathematically sensible in any scenario whereeltype(A)
is some set and+
,*
are defined as operations such as unions & string concatenation or convex hull & minkowski sums. In my application (which I cannot disclose in detail), I need to use such sets, but also support different array structures (Array, Diagonal, sparse etc.). This makes it really attractive to rely on generic fallbacks and not implement my own version.