From 0a65c2ed7d44473b90ed1ee473c8195622c19c00 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Fri, 14 Aug 2026 11:20:48 -0400 Subject: [PATCH] Avoid ambiguous reverse promotion in DiffCache Co-Authored-By: Chris Rackauckas --- src/PreallocationTools.jl | 12 +++++++++--- test/sparse_connectivity_tracer.jl | 12 ++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/PreallocationTools.jl b/src/PreallocationTools.jl index aff7638..c57b11c 100644 --- a/src/PreallocationTools.jl +++ b/src/PreallocationTools.jl @@ -250,8 +250,14 @@ function get_tmp(dc::FixedSizeDiffCache, u::Union{Number, AbstractArray}) return get_tmp(dc, eltype(u)) end +function _promotes_to_primal(::Type{P}, ::Type{T}) where {P, T} + # Query the requested type first so its custom rule can avoid an ambiguous reverse rule. + promoted = Base.promote_rule(T, P) + return promoted === Union{} ? promote_type(P, T) <: P : promoted <: P +end + function get_tmp(dc::FixedSizeDiffCache, ::Type{T}) where {T <: Number} - return if promote_type(eltype(dc.du), T) <: eltype(dc.du) + return if _promotes_to_primal(eltype(dc.du), T) dc.du else _typed_tmp(dc, T) @@ -394,7 +400,7 @@ function _typed_tmp(dc, ::Type{T}) where {T} end function get_tmp(dc::DiffCache, u::Union{Number, AbstractArray}) - return if promote_type(eltype(dc.du), eltype(u)) <: eltype(dc.du) + return if _promotes_to_primal(eltype(dc.du), eltype(u)) dc.du else _typed_tmp(dc, eltype(u)) @@ -402,7 +408,7 @@ function get_tmp(dc::DiffCache, u::Union{Number, AbstractArray}) end function get_tmp(dc::DiffCache, ::Type{T}) where {T <: Number} - return if promote_type(eltype(dc.du), T) <: eltype(dc.du) + return if _promotes_to_primal(eltype(dc.du), T) dc.du else _typed_tmp(dc, T) diff --git a/test/sparse_connectivity_tracer.jl b/test/sparse_connectivity_tracer.jl index 525b5cf..87cc550 100644 --- a/test/sparse_connectivity_tracer.jl +++ b/test/sparse_connectivity_tracer.jl @@ -2,6 +2,18 @@ module TestSparseConnectivityTracer using PreallocationTools, SparseConnectivityTracer, ForwardDiff, SparseArrays, Test +@testset "BigFloat cache" begin + T = jacobian_eltype(BigFloat[1], TracerLocalSparsityDetector()) + input = Vector{T}(undef, 1) + + for cache in (DiffCache(BigFloat[1]), FixedSizeDiffCache(BigFloat[1], 1)) + type_workspace = @inferred get_tmp(cache, T) + array_workspace = @inferred get_tmp(cache, input) + @test eltype(type_workspace) === T + @test Base.mightalias(type_workspace, array_workspace) + end +end + function f1(u, cache) c = get_tmp(cache, u) # This will throw if a fallback definition is used