Skip to content

Make NonlinearSolution's retcode field type a parameter - #1563

Closed
ChrisRackauckas-Claude wants to merge 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:traced-retcode
Closed

ChrisRackauckas-Claude wants to merge 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:traced-retcode

Conversation

@ChrisRackauckas-Claude

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Aug 29, 2026 •

Copy link
Copy Markdown
Member

Draft. Ignore this PR until reviewed by @ChrisRackauckas.

What changed and why

NonlinearSolution.retcode was declared ::ReturnCode.T. Inside a Reactant-compiled solve the return code is a traced enum (TracedRNumber{ReturnCode.T}, EnzymeAD/Reactant.jl#3232), and a concretely typed field cannot hold it: Reactant rebuilds structs with traced field types and raises NoFieldMatchError for fixed ones. This makes the field retcode::RC with RC appended to the type parameters. build_solution and the positional NonlinearSolution(u, resid, prob, alg, retcode, ...) constructor are unchanged for callers; on the host RC === ReturnCode.T exactly as before.

successful_retcode(retcode) gains a fallback that converts other scalar carriers of a return code (a Reactant ConcreteRNumber{ReturnCode.T} after the compiled call) to ReturnCode.T first, so successful_retcode(sol) keeps working on such solutions.

This is the SciMLBase half of letting NonlinearSolve solvers run under Reactant.@jit without a shadow solution type (SciML/NonlinearSolve.jl#1197).

Compatibility — this is breaking for released NonlinearSolve until its constructors are released

Appending a type parameter is only visible to code that spells out all of NonlinearSolution's parameters. A GitHub code search over the SciML org finds three such sites, all in NonlinearSolve.jl: build_solution_less_specialize (lib/NonlinearSolveBase/src/polyalg.jl), SCCNonlinearSolve, and nonlinear_solution_new_alg (lib/SimpleNonlinearSolve/src/utils.jl). The released versions of those packages therefore fail to precompile against this branch, which is what the red Documentation and downstream lanes here show (MethodError: no method matching (NonlinearSolution{...10 parameters...})(...) from build_solution_less_specialize).

The fix on the NonlinearSolve side is small and works with both layouts (it picks the layout at load time from fieldtype(NonlinearSolution, :retcode)). It was carved out as SciML/NonlinearSolve.jl#1214, which was closed; it remains part of SciML/NonlinearSolve.jl#1197. Until a NonlinearSolveBase/SCCNonlinearSolve/SimpleNonlinearSolve release carries it, this PR breaks the released NonlinearSolve, which is what the downstream lanes here show. Given that, whether this is a minor (3.51.0, as set) or a major bump is the reviewer's call; nothing else in the org constructs NonlinearSolution with explicit parameters.

Verification

$ julia --project=. -e 'using Pkg; Pkg.test()'    # default group, Julia 1.12.4
     Testing SciMLBase tests passed

(The explicit-parameter construction in test/solution_interface.jl is updated and the @inferred solution_new_original_retcode check there passes.)

Formatted with Runic 1.10.0; typos clean on the changed files.

Not verified

  • Downstream packages other than NonlinearSolve.jl (the companion PR runs its Reactant group against this branch).

🤖 Generated with Claude Code (model: claude-fable-5) on behalf of Chris Rackauckas. Session: https://claude.ai/code/session_016LsC6pp9z6s5EABX9DnVjE

`retcode::ReturnCode.T` cannot hold a return code computed inside a Reactant
compiled program, where it is a traced enum. The field becomes `retcode::RC`
with `RC` appended to the type parameters; `build_solution` and the positional
constructor are unchanged for callers. `successful_retcode` gains a fallback
that converts other scalar carriers (e.g. a Reactant `ConcreteRNumber`) to
`ReturnCode.T` first.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Agent-Harness: Claude Code 2.1.251
Agent-Model: claude-fable-5
Agent-Session: https://claude.ai/code/session_016LsC6pp9z6s5EABX9DnVjE
@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

Companion PRs using this: SciML/NonlinearSolve.jl#1197 (NonlinearSolveBase/first-order under Reactant; pins this branch in its Reactant test group) and SciML/NonlinearSolve.jl#1213 (SimpleNonlinearSolve, stacked on it).

🤖 Posted by an AI agent (Claude Code, model claude-fable-5) on behalf of Chris Rackauckas. Session: https://claude.ai/code/session_016LsC6pp9z6s5EABX9DnVjE

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

CI triage: every red lane here (Documentation and the downstream tests) is the released NonlinearSolveBase/SCCNonlinearSolve/SimpleNonlinearSolve failing to precompile against the new NonlinearSolution layout — they spell out all of its type parameters. The fix on that side is SciML/NonlinearSolve.jl#1214 (layout-agnostic constructors, works with both layouts); once it is merged and released, this PR is non-breaking for the ecosystem. The PR body's compatibility section is updated accordingly.

🤖 Posted by an AI agent (Claude Code, model claude-fable-5) on behalf of Chris Rackauckas. Session: https://claude.ai/code/session_016LsC6pp9z6s5EABX9DnVjE

@ChrisRackauckas

Copy link
Copy Markdown
Member

@wsmoses is there no better way to handle this?

@wsmoses

wsmoses commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

yeah if that type could contain traced data, either it needs to be extensible enough to contain a traced version [e.g. is abstract], or can be templated to take the traced struct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants