Skip to content

Commit bdec814

Browse files
Add inference tests for ForwardDiff Dual problems
- Add @inferred tests to verify init returns concrete DualLinearCache type - Update GenericLUFactorization test to expect DualLinearCache (optimization moved to solve-time) - Add test for solve correctness with GenericLUFactorization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 4882e97 commit bdec814

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

test/forwarddiff_overloads.jl

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,37 @@ overload_x_p = solve!(cache, UMFPACKFactorization())
196196
backslash_x_p = A \ b
197197
@test (overload_x_p, backslash_x_p, rtol = 1e-9)
198198

199-
# Test that GenericLU doesn't create a DualLinearCache
199+
# Test type inference for init with ForwardDiff Dual numbers
200+
# This ensures init returns a concrete type (not a Union) for type stability
200201
A, b = h([ForwardDiff.Dual(5.0, 1.0, 0.0), ForwardDiff.Dual(5.0, 0.0, 1.0)])
201202

202203
prob = LinearProblem(A, b)
203-
@test init(prob, GenericLUFactorization()) isa LinearSolve.LinearCache
204204

205-
@test init(prob) isa LinearSolve.LinearCache
205+
# GenericLUFactorization now returns DualLinearCache for type stability
206+
# (the optimization for GenericLU happens at solve-time instead of init-time)
207+
@test init(prob, GenericLUFactorization()) isa LinearSolve.LinearSolveForwardDiffExt.DualLinearCache
206208

207-
# Test that SparspakFactorization doesn't create a DualLinearCache
209+
# Test inference with explicit algorithm
210+
@test (@inferred init(prob, LUFactorization())) isa LinearSolve.LinearSolveForwardDiffExt.DualLinearCache
211+
@test (@inferred init(prob, GenericLUFactorization())) isa LinearSolve.LinearSolveForwardDiffExt.DualLinearCache
212+
213+
# Test inference with default algorithm (nothing) - this was the main bug
214+
# Previously returned Union{LinearCache, DualLinearCache} due to runtime conditional
215+
@test (@inferred init(prob, nothing)) isa LinearSolve.LinearSolveForwardDiffExt.DualLinearCache
216+
217+
# Test that SparspakFactorization still opts out (sparse solvers can't handle Duals the same way)
208218
A, b = h([ForwardDiff.Dual(5.0, 1.0, 0.0), ForwardDiff.Dual(5.0, 0.0, 1.0)])
209219

210220
prob = LinearProblem(sparse(A), b)
211221
@test init(prob, SparspakFactorization()) isa LinearSolve.LinearCache
212222

223+
# Test that solve still works correctly with GenericLUFactorization
224+
A, b = h([ForwardDiff.Dual(5.0, 1.0, 0.0), ForwardDiff.Dual(5.0, 0.0, 1.0)])
225+
prob = LinearProblem(A, b)
226+
sol_generic = solve(prob, GenericLUFactorization())
227+
backslash_result = A \ b
228+
@test (sol_generic.u, backslash_result, rtol = 1e-9)
229+
213230
# Test ComponentArray with ForwardDiff (Issue SciML/DifferentialEquations.jl#1110)
214231
# This tests that ArrayInterface.restructure preserves ComponentArray structure
215232

0 commit comments

Comments
 (0)