From 7415b53b48be0b10ec235ab74e8e2c3c8a014225 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Wed, 27 May 2026 07:29:51 +0000 Subject: [PATCH] Resolve Aqua method ambiguity for convert(::Static.{True,False,StaticInt{N}}, ::LazyMulAdd) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Aqua.test_ambiguities` flags three ambiguities between Static.jl's specific `convert(::Type{Static.True/False/StaticInt{N}}, ::Number)` overloads and this package's generic `convert(::Type{T}, ::LazyMulAdd) where T<:Number` at lazymul.jl:25. Both methods match `convert(Static.True, ::LazyMulAdd)` etc. — Static constrains the first arg, VB constrains the second, neither is strictly more specific. Add three disambiguating methods that fix both arg types and forward to `Static`'s convert on the materialized LazyMulAdd value. This matches Static.jl's semantics (which raises `ArgumentError` if the materialized number doesn't equal the StaticNumber's known value) while preserving the lazy evaluation discipline of the other `convert(::Type{T}, ::LazyMulAdd)` overload. This ambiguity exists on master CI today (visible since whichever Static.jl / Aqua bump exposed it) — it's not introduced by either of the in-flight macOS-ARM PRs (#127, JuliaSIMD/LoopVectorization.jl#569), just orthogonal CI hygiene to keep `Aqua.test_ambiguities` clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lazymul.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/lazymul.jl b/src/lazymul.jl index 285a3245..819687ca 100644 --- a/src/lazymul.jl +++ b/src/lazymul.jl @@ -28,6 +28,25 @@ end ::Type{LazyMulAdd{M,O,I}}, a::LazyMulAdd{M,O,I} ) where {M,O,I} = a +# Disambiguate the generic `convert(::Type{T<:Number}, ::LazyMulAdd)` above +# against Static.jl's `convert(::Type{Static.{True,False,StaticInt{N}}}, +# ::Number)` methods. Aqua flags both as matching `convert(Static.True, +# ::LazyMulAdd)` etc., since `LazyMulAdd <: Number` and neither method is +# strictly more specific. Forward to `Static`'s convert on the materialized +# value so the StaticBool / StaticInt singletons come out, matching what +# Static.jl produces for any Number input. +@inline Base.convert( + ::Type{Static.True}, + a::LazyMulAdd{M,O,I} +) where {M,O,I} = convert(Static.True, _materialize(a)) +@inline Base.convert( + ::Type{Static.False}, + a::LazyMulAdd{M,O,I} +) where {M,O,I} = convert(Static.False, _materialize(a)) +@inline Base.convert( + ::Type{Static.StaticInt{N}}, + a::LazyMulAdd{M,O,I} +) where {M,O,I,N} = convert(Static.StaticInt{N}, _materialize(a)) # @inline Base.convert(::Type{LazyMulAdd{M,O,I}}, a::LazyMulAdd{M}) where {M,O,I} = a # @inline Base.convert(::Type{LazyMulAdd{M,T,I}}, a::LazyMulAdd{M,StaticInt{O},I}) where {M,O,I,T} = a