Skip to content

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

Merged
ChrisRackauckas merged 3 commits into
SciML:masterfrom
ChrisRackauckas-Claude:agent/1619-nonlinear-retcode-param
Sep 26, 2026
Merged

ChrisRackauckas merged 3 commits into
SciML:masterfrom
ChrisRackauckas-Claude:agent/1619-nonlinear-retcode-param

Conversation

@ChrisRackauckas-Claude

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

Please ignore this draft until reviewed by @ChrisRackauckas.

What changed and why

NonlinearSolution.retcode was declared ::ReturnCode.T, so a return code carried by another scalar type (e.g. a Reactant TracedEnum produced inside a compiled solver loop) cannot be stored in it. This mirrors the ODESolution change from #1564 (released as minor v3.56.0): the field becomes retcode::RC with RC a new trailing type parameter, solution_new_retcode gains a NonlinearSolution method that preserves the carrier type, and successful_retcode's existing convertible-carrier fallback applies. Positional and build_solution constructors are unchanged for ordinary ReturnCode.T values, and no version bump is included per project policy.

Because appending RC turns the ten-parameter spelling NonlinearSolution{T,N,uType,R,P,A,O,uType2,S,Tr} into a non-callable UnionAll, a constructor covering that spelling is added; it takes RC from the retcode argument. Unlike #1563 (which failed released NonlinearSolve precompilation), released downstream code that constructs with all parameters spelled out keeps working — verified below.

This change is non-breaking for ordinary constructors. SciML/NonlinearSolve.jl#1332 keeps vector-form SCC users' legacy ten-parameter FunctionWrapper callbacks converting by matching the declared SubArray element type (including when the legacy wrapper is not the first element of a mixed Any[...] container).

Merge/release only after SciML/NonlinearSolve.jl#1332 is merged and released. Otherwise NonlinearSolve.jl's SCC CI goes red on the next SciMLBase release.

Test evidence

New testset NonlinearSolution retcode type parameter in test/solution_interface.jl. Negative control — same solution_new_retcode call on unmodified origin/master source (src/solutions/nonlinear_solutions.jl checked out from master, everything else identical):

ERROR: LoadError: MethodError: no method matching solution_new_retcode(::NonlinearSolution{Float64, 1, Vector{Float64}, Vector{Float64}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, ::Base.RefValue{SciMLBase.ReturnCode.T})
The function `solution_new_retcode` exists, but no method is defined for this combination of argument types.

With this branch the same script prints retcode fieldtype: Base.RefValue{SciMLBase.ReturnCode.T}, and the full new testset passes inside GROUP=Core below.

Local test runs (Julia 1.12.7, Pkg.test())

Re-run on this head from job scratch (agent/1619-nonlinear-retcode-param):

GROUP=Core:

Remake        | 4605   4605  3m57.7s
     Testing SciMLBase tests passed
SCIMLBASE_CORE_EXIT=0

GROUP=QA (JULIA_CONDAPKG_BACKEND=Null JULIA_PYTHONCALL_EXE=/usr/bin/python3):

Test Summary: | Pass  Total     Time
QA            |  123    123  3m01.5s
     Testing SciMLBase tests passed
SCIMLBASE_QA_EXIT=0

Lint/format on touched files (incl. comment-only follow-up 2fe56b4d): Runic 0, typos 0.

Downstream compatibility

Hit Verdict
NonlinearSolveBase / SimpleNonlinearSolve ten-parameter constructors Unaffected — compat constructor; Core suites pass against this branch.
Released SCCNonlinearSolve 1.15.4 Core against this branch Fails one assertion: isconcretetype(eltype(scc_sol_debug.original)) in core_tests__item4.jl (72 pass / 1 fail / 73). Correct u / Success retcodes; the ten-parameter spelling is a UnionAll, so the buffer/original eltype is abstract. Same concreteness trade-off as #1564. Fixed by SciML/NonlinearSolve.jl#1332.
Code that spells the ten-parameter NonlinearSolution type Gets an abstract-eltype buffer/original (correct results, loses concreteness) until #1332 is released.
#1332 + this branch SCC Core green, including legacy homogeneous wrappers and mixed Any[plain, legacy_FW] (14/14 in item8).

Why non-breaking

Every public spelling and call path is preserved: the generic constructor, build_solution, ::NonlinearSolution annotations, and ten-parameter spelled constructor calls (via the compat method). The observable residual is that NonlinearSolution{10 params} denotes a UnionAll rather than a concrete type — the same accepted trade-off as the trailing-RC change to ODESolution in #1564 (minor v3.56.0). Companion #1332 restores concrete eltype for the updated SCC signature and preserves legacy wrapper conversion.

Not verified

  • Reactant-side tracing itself.
  • GROUP=Downstream/DownstreamAD/Python; docs build (no docstring changes).

Reviewer push-back points

  • Confirm abstract eltype for ten-parameter spellers is acceptable under a non-breaking (no bump / minor) release, as for Support compiled ODE return codes and specialization #1564.
  • The compat constructor is a catch-all on the 10-parameter spelling; fully-spelled NonlinearSolution{...,RC}(args...) still uses the default inner constructor.

Closes #1619


Please ignore this draft until reviewed by @ChrisRackauckas.

Devin CLI 3000.11.3 (original) + Cursor Agent CLI 2026.09.26-dd393fe, model auto (round-2 text/comment + #1332 companion). Transcript: /home/crackauc/sandbox/agent-jobs/NonlinearSolve.jl/jobs/1332-cursor/log.txt on amdci2.julia.csail.mit.edu

ChrisRackauckas and others added 2 commits September 26, 2026 08:22
`NonlinearSolution.retcode` was declared `::ReturnCode.T`, so a return
code carried by another scalar type (e.g. a Reactant `TracedEnum`
produced inside a compiled solver loop) cannot be stored in it.
Mirror the ODESolution change (SciML#1564): the field becomes `retcode::RC`
with `RC` a new trailing type parameter, and `solution_new_retcode`
gains a `NonlinearSolution` method that preserves the carrier type.

A `NonlinearSolution{T,N,uType,R,P,A,O,uType2,S,Tr}` type application
now denotes a non-callable UnionAll, so a constructor covering that
ten-parameter spelling keeps downstream code that spells out the
parameters working, inferring `RC` from the `retcode` argument.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Devin <noreply@cognition.ai>
Agent-Harness: Devin CLI 3000.11.3
Agent-Model: swe-2-high
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/SciMLBase.jl/jobs/1619-devin/log.txt on amdci2.julia.csail.mit.edu
The compatibility constructor keeps every existing public spelling and
call working. The only observed downstream effect is a concreteness
assertion on SCCNonlinearSolve's internal `sols` buffer (a performance
property of its own code, not a public-API break), and the identical
ODESolution change in SciML#1564 shipped as a minor release. Leave the
version untouched per project policy for behavior-preserving changes.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Devin <noreply@cognition.ai>
Agent-Harness: Devin CLI 3000.11.3
Agent-Model: swe-2-high
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/SciMLBase.jl/jobs/1619-devin/log.txt on amdci2.julia.csail.mit.edu
State the constructibility invariant without naming an external
call site, matching the package comment convention.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/NonlinearSolve.jl/jobs/1332-cursor/log.txt on amdci2.julia.csail.mit.edu
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.

Make NonlinearSolution's retcode field type a type parameter (traced return codes)

2 participants