Skip to content

Lost generality of _generic_matmatmul in 1.11 #1095

Closed
JuliaLang/julia
#56089
@laggvar

Description

@laggvar

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 where eltype(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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    regression 1.11Regression in the 1.11 release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions