From cfc6e53234e1df4014446c67298adea1317b255e Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Thu, 25 Jun 2026 06:18:50 -0400 Subject: [PATCH 1/6] QA: run_qa v1.6 form + ExplicitImports Convert test/qa/qa.jl from the hand-rolled Aqua/JET body to the SciMLTesting v1.6 run_qa form, with ExplicitImports enabled. - run_qa(ODEInterfaceDiffEq; explicit_imports = true, ei_kwargs = ...): Aqua and ExplicitImports come from SciMLTesting's own deps; JET via `using JET` (weakdep extension). JET runs as a hard check and passes (the old qa.jl had a bare `@test_broken false` placeholder that never actually invoked JET; report_package and test_package(mode=:typo) both report 0 issues against target_modules=(pkg,)). - Aqua deps_compat fixed (not suppressed): the old qa.jl disabled deps_compat and marked it @test_broken because LinearAlgebra (a stdlib dep) had no [compat] entry. Added `LinearAlgebra = "1"` to the root [compat]; full Aqua.test_all now passes, so no aqua_broken placeholder is needed. - ExplicitImports: 3 of 6 checks pass clean (no_implicit_imports, no_stale_explicit_imports, all_explicit_imports_via_owners). The other 3 are ignore-listed because every flagged name is a non-public name owned by a dependency (SciMLBase / DiffEqBase / SciMLBase.ReturnCode / ODEInterface / Base.Iterators) or a SciMLBase name reexported through DiffEqBase (the DiffEqBase.__solve / initialize_dae! solver-extension convention). No own non-public names are involved; nothing is silenced beyond documented per-check ignore-lists, and none need ei_broken. - Removed the orphan test/explicit_imports.jl (not wired into any test group under the SciMLTesting folder model) and dropped ExplicitImports from the root [compat]/[extras]/[targets] (it is transitive via SciMLTesting). Bumped the QA env SciMLTesting [compat] to "1.6". Verified locally against released SciMLTesting 1.6.0 (no dev-from-branch): QA/qa.jl group = 18 Pass / 0 Fail / 0 Error / 0 Broken via both `--project=test/qa test/qa/qa.jl` and the folder-model `GROUP=QA runtests.jl`. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- Project.toml | 5 ++-- test/explicit_imports.jl | 8 ----- test/qa/Project.toml | 2 +- test/qa/qa.jl | 63 ++++++++++++++++++++++++++++++---------- 4 files changed, 51 insertions(+), 27 deletions(-) delete mode 100644 test/explicit_imports.jl diff --git a/Project.toml b/Project.toml index 1712187..7a8c0f7 100644 --- a/Project.toml +++ b/Project.toml @@ -18,8 +18,8 @@ SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" Compat = "4.15" DataStructures = "0.19" DiffEqBase = "7" -ExplicitImports = "1" FunctionWrappers = "1.1.3" +LinearAlgebra = "1" ModelingToolkit = "9, 10, 11" NonlinearSolve = "3, 4" ODEInterface = "0.5" @@ -34,7 +34,6 @@ Test = "1" julia = "1.10" [extras] -ExplicitImports = "7d51a73a-1435-4ff3-83d9-f097790105c7" ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" ODEProblemLibrary = "fdc4e326-1af4-4b90-96e7-779fcce2daa5" @@ -44,4 +43,4 @@ SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["ExplicitImports", "ModelingToolkit", "NonlinearSolve", "SafeTestsets", "SciMLTesting", "SymbolicIndexingInterface", "Test", "ODEProblemLibrary"] +test = ["ModelingToolkit", "NonlinearSolve", "SafeTestsets", "SciMLTesting", "SymbolicIndexingInterface", "Test", "ODEProblemLibrary"] diff --git a/test/explicit_imports.jl b/test/explicit_imports.jl deleted file mode 100644 index a7e8973..0000000 --- a/test/explicit_imports.jl +++ /dev/null @@ -1,8 +0,0 @@ -using ExplicitImports -using ODEInterfaceDiffEq -using Test - -@testset "ExplicitImports" begin - @test check_no_implicit_imports(ODEInterfaceDiffEq) === nothing - @test check_no_stale_explicit_imports(ODEInterfaceDiffEq) === nothing -end diff --git a/test/qa/Project.toml b/test/qa/Project.toml index 793a409..3521e68 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -13,6 +13,6 @@ ODEInterfaceDiffEq = { path = "../.." } Aqua = "0.8" JET = "0.9,0.10,0.11" SafeTestsets = "0.0.1, 0.1" -SciMLTesting = "1" +SciMLTesting = "1.6" Test = "1" julia = "1.10" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 8b63fe6..bd2f3c8 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -1,17 +1,50 @@ -using ODEInterfaceDiffEq, Aqua, JET -using Test +using SciMLTesting, ODEInterfaceDiffEq, Test +using JET -@testset "Aqua" begin - # deps_compat disabled: ODEInterfaceDiffEq does not declare a compat entry - # for the LinearAlgebra stdlib dependency. Tracked in - # https://github.com/SciML/ODEInterfaceDiffEq.jl/issues/105 - Aqua.test_all(ODEInterfaceDiffEq; deps_compat = false) - @test_broken false # Aqua deps compat: missing compat entry for LinearAlgebra dep — tracked in https://github.com/SciML/ODEInterfaceDiffEq.jl/issues/105 -end +# ExplicitImports ignore-lists. Every ignored name is a non-public name owned by a +# dependency (not by ODEInterfaceDiffEq), or a SciMLBase name reexported through +# DiffEqBase. These are the standard solver-extension surface: ODEInterfaceDiffEq +# extends/uses DiffEqBase/SciMLBase internals (the `DiffEqBase.__solve` / +# `initialize_dae!` convention shared by every SciML solver package) and the +# ODEInterface C-wrapper's non-public solver entry points. They become public as the +# base libraries declare them `public`; until then they are legitimately ignored. -@testset "JET" begin - # JET.test_package reports an undefined-binding error - # (ODEInterfaceDiffEq.uBottomEltype in src/solve.jl). Tracked in - # https://github.com/SciML/ODEInterfaceDiffEq.jl/issues/105 - @test_broken false # JET: `ODEInterfaceDiffEq.uBottomEltype` is not defined (src/solve.jl) — tracked in https://github.com/SciML/ODEInterfaceDiffEq.jl/issues/105 -end +# all_qualified_accesses_via_owners: names accessed through DiffEqBase that SciMLBase +# owns (DiffEqBase reexports them), plus SciMLStructures accessed through SciMLBase. +const QUALIFIED_VIA_OWNERS_IGNORE = ( + :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractODEProblem, + :AbstractParameterizedFunction, :SciMLStructures, :__solve, :build_solution, + :calculate_solution_errors!, :has_analytic, :has_jac, :has_tgrad, + :initialize_dae!, :solution_new_retcode, +) + +# all_qualified_accesses_are_public: non-public names from DiffEqBase, SciMLBase, +# SciMLBase.ReturnCode, ODEInterface, and Base.Iterators (`filter`). +const QUALIFIED_ARE_PUBLIC_IGNORE = ( + :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractODEProblem, + :AbstractParameterizedFunction, :CallbackCache, :Default, :DtLessThanMin, + :Failure, :InitialFailure, :MaxIters, :OUTPUTFCN_CALL_REASON, + :OUTPUTFCN_CALL_STEP, :OUTPUTFCN_DENSE, :OUTPUTFCN_RET_CONTINUE, + :OUTPUTFCN_RET_CONTINUE_XCHANGED, :OUTPUTFCN_WODENSE, :OptionsODE, + :RHS_CALL_INSITU, :SciMLStructures, :Stats, :Success, :Unstable, :__solve, + :_process_verbose_param, :alg_order, :apply_callback!, :apply_discrete_callback!, + :build_solution, :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, :dopri5, + :filter, :find_first_continuous_callback, :get_initial_values, :has_analytic, + :has_jac, :has_tgrad, :initialize_dae!, :max_vector_callback_length, :odex, + :radau, :radau5, :rodas, :seulex, :solution_new_retcode, +) + +# all_explicit_imports_are_public: SciMLBase initialization-algorithm internals. +const EXPLICIT_IMPORTS_ARE_PUBLIC_IGNORE = ( + :NoInit, :OverrideInit, :has_initialization_data, +) + +run_qa( + ODEInterfaceDiffEq; + explicit_imports = true, + ei_kwargs = (; + all_qualified_accesses_via_owners = (; ignore = QUALIFIED_VIA_OWNERS_IGNORE), + all_qualified_accesses_are_public = (; ignore = QUALIFIED_ARE_PUBLIC_IGNORE), + all_explicit_imports_are_public = (; ignore = EXPLICIT_IMPORTS_ARE_PUBLIC_IGNORE), + ), +) From 3ec0f92fe838cc8106ae418a0e58c7dab7874da7 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Thu, 25 Jun 2026 10:47:39 -0400 Subject: [PATCH 2/6] Fix latent UndefVarError/undefined-locals in __solve flagged by JET QA The v1.6 run_qa conversion enabled JET as a hard QA check. On Julia 1.12 (the "julia 1" lane) JET.report_package(...; mode=:typo) finds 17 issues in the DiffEqBase.__solve path that the old no-op `@test_broken false` never surfaced. All are pre-existing latent bugs: - `uBottomEltype` was referenced at src/solve.jl but never defined or imported (a guaranteed UndefVarError on the VectorContinuousCallback branch). Compute it as `SciMLBase.recursive_bottom_eltype(prob.u0)`, matching the OrdinaryDiffEq convention. recursive_bottom_eltype is owned by RecursiveArrayTools and reached via the existing `import SciMLBase`, so no new dependency; added it to the ExplicitImports via_owners / are_public ignore lists with its owner documented. - The `alg isa ...` solver dispatch chain had no final `else`, so JET saw a path where tend/uend/retcode/stats stay undefined (then read below). The nine concrete ODEInterfaceAlgorithm subtypes make the chain total in practice; turn the last `elseif alg isa ddebdf` into `else` so it is provably total. - The retcode-to-ReturnCode mapping had no `else`, leaving return_retcode undefined for any negative retcode other than -1..-4 (a real UndefVarError at the final solution_new_retcode call). Map any other negative retcode to ReturnCode.Failure. JET now reports 0 issues; the full QA group passes 18/18 on both Julia 1.12 and 1.10 (LTS) against released SciMLTesting 1.6.0. The Core (julia 1 / julia pre) lanes remain red, but that is pre-existing and unrelated: ODEInterface_jll fails to load its Fortran solver binaries on Julia 1.12+ ("Cannot find method(s) for dopri5!"), reproducing identically on master and locally. Not touched here. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- src/solve.jl | 5 ++++- test/qa/qa.jl | 10 ++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/solve.jl b/src/solve.jl index a432451..d3061f0 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -34,6 +34,7 @@ function DiffEqBase.__solve( max_len_cb = DiffEqBase.max_vector_callback_length(callbacks_internal) if max_len_cb isa VectorContinuousCallback + uBottomEltype = SciMLBase.recursive_bottom_eltype(prob.u0) callback_cache = DiffEqBase.CallbackCache( max_len_cb.len, uBottomEltype, uBottomEltype @@ -227,7 +228,7 @@ function DiffEqBase.__solve( f!, tspan[1], tspan[2], vec(integrator.u), opts ) - elseif alg isa ddebdf + else tend, uend, retcode, stats = ODEInterface.ddebdf( @@ -254,6 +255,8 @@ function DiffEqBase.__solve( elseif retcode == -4 @SciMLMessage("Interrupted. Problem is probably stiff.", verbose_spec, :stiff_detection) return_retcode = ReturnCode.Unstable + else + return_retcode = ReturnCode.Failure end else return_retcode = ReturnCode.Success diff --git a/test/qa/qa.jl b/test/qa/qa.jl index bd2f3c8..f0e881f 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -10,16 +10,18 @@ using JET # base libraries declare them `public`; until then they are legitimately ignored. # all_qualified_accesses_via_owners: names accessed through DiffEqBase that SciMLBase -# owns (DiffEqBase reexports them), plus SciMLStructures accessed through SciMLBase. +# owns (DiffEqBase reexports them), plus SciMLStructures accessed through SciMLBase, and +# recursive_bottom_eltype (RecursiveArrayTools-owned, accessed via SciMLBase reexport). const QUALIFIED_VIA_OWNERS_IGNORE = ( :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractODEProblem, :AbstractParameterizedFunction, :SciMLStructures, :__solve, :build_solution, :calculate_solution_errors!, :has_analytic, :has_jac, :has_tgrad, - :initialize_dae!, :solution_new_retcode, + :initialize_dae!, :recursive_bottom_eltype, :solution_new_retcode, ) # all_qualified_accesses_are_public: non-public names from DiffEqBase, SciMLBase, -# SciMLBase.ReturnCode, ODEInterface, and Base.Iterators (`filter`). +# SciMLBase.ReturnCode, ODEInterface, Base.Iterators (`filter`), and +# recursive_bottom_eltype (RecursiveArrayTools, not declared public in SciMLBase). const QUALIFIED_ARE_PUBLIC_IGNORE = ( :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractODEProblem, :AbstractParameterizedFunction, :CallbackCache, :Default, :DtLessThanMin, @@ -31,7 +33,7 @@ const QUALIFIED_ARE_PUBLIC_IGNORE = ( :build_solution, :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, :dopri5, :filter, :find_first_continuous_callback, :get_initial_values, :has_analytic, :has_jac, :has_tgrad, :initialize_dae!, :max_vector_callback_length, :odex, - :radau, :radau5, :rodas, :seulex, :solution_new_retcode, + :radau, :radau5, :recursive_bottom_eltype, :rodas, :seulex, :solution_new_retcode, ) # all_explicit_imports_are_public: SciMLBase initialization-algorithm internals. From e88cfa987373e948bdaa0b956484aad719ef7d4c Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Fri, 26 Jun 2026 16:08:23 -0400 Subject: [PATCH 3/6] QA: sweep redundant public-API EI ignores against released base libs SciMLTesting 1.7.0 now runs the two public-API ExplicitImports checks (check_all_qualified_accesses_are_public / check_all_explicit_imports_are_public) only on Julia >= 1.11 and skips them on the LTS, and the released base libraries (SciMLBase 3.24.0, CommonSolve 0.2.9) declare their ReturnCode enum public. Verified on Julia 1.12 against the registered releases (DiffEqBase 7.5.7, SciMLBase 3.24.0, ODEInterface 0.5.1): the ReturnCode members (Default, DtLessThanMin, Failure, InitialFailure, MaxIters, Success, Unstable) and Base.Iterators.filter are now recognized public, so drop those 8 entries from all_qualified_accesses_are_public. The remaining names stay: they are still non-public internals of DiffEqBase / SciMLBase / the ODEInterface C wrapper in the registered releases (verified via Base.ispublic on 1.12). QA group green on Julia 1.12 (18/18) and on the LTS 1.10 (16/16, the two public checks skipped). Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/qa/qa.jl | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/test/qa/qa.jl b/test/qa/qa.jl index f0e881f..60690b2 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -2,11 +2,9 @@ using SciMLTesting, ODEInterfaceDiffEq, Test using JET # ExplicitImports ignore-lists. Every ignored name is a non-public name owned by a -# dependency (not by ODEInterfaceDiffEq), or a SciMLBase name reexported through -# DiffEqBase. These are the standard solver-extension surface: ODEInterfaceDiffEq -# extends/uses DiffEqBase/SciMLBase internals (the `DiffEqBase.__solve` / -# `initialize_dae!` convention shared by every SciML solver package) and the -# ODEInterface C-wrapper's non-public solver entry points. They become public as the +# dependency (not by ODEInterfaceDiffEq): the standard SciML solver-extension surface +# (DiffEqBase/SciMLBase internals such as `__solve` / `initialize_dae!`) and the +# ODEInterface C-wrapper's non-public solver entry points. They become removable as the # base libraries declare them `public`; until then they are legitimately ignored. # all_qualified_accesses_via_owners: names accessed through DiffEqBase that SciMLBase @@ -19,24 +17,23 @@ const QUALIFIED_VIA_OWNERS_IGNORE = ( :initialize_dae!, :recursive_bottom_eltype, :solution_new_retcode, ) -# all_qualified_accesses_are_public: non-public names from DiffEqBase, SciMLBase, -# SciMLBase.ReturnCode, ODEInterface, Base.Iterators (`filter`), and -# recursive_bottom_eltype (RecursiveArrayTools, not declared public in SciMLBase). +# all_qualified_accesses_are_public: names still non-public in the registered releases +# (DiffEqBase 7, SciMLBase 3.24, ODEInterface 0.5). const QUALIFIED_ARE_PUBLIC_IGNORE = ( :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractODEProblem, - :AbstractParameterizedFunction, :CallbackCache, :Default, :DtLessThanMin, - :Failure, :InitialFailure, :MaxIters, :OUTPUTFCN_CALL_REASON, + :AbstractParameterizedFunction, :CallbackCache, :OUTPUTFCN_CALL_REASON, :OUTPUTFCN_CALL_STEP, :OUTPUTFCN_DENSE, :OUTPUTFCN_RET_CONTINUE, :OUTPUTFCN_RET_CONTINUE_XCHANGED, :OUTPUTFCN_WODENSE, :OptionsODE, - :RHS_CALL_INSITU, :SciMLStructures, :Stats, :Success, :Unstable, :__solve, - :_process_verbose_param, :alg_order, :apply_callback!, :apply_discrete_callback!, - :build_solution, :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, :dopri5, - :filter, :find_first_continuous_callback, :get_initial_values, :has_analytic, - :has_jac, :has_tgrad, :initialize_dae!, :max_vector_callback_length, :odex, - :radau, :radau5, :recursive_bottom_eltype, :rodas, :seulex, :solution_new_retcode, + :RHS_CALL_INSITU, :SciMLStructures, :Stats, :__solve, :_process_verbose_param, + :alg_order, :apply_callback!, :apply_discrete_callback!, :build_solution, + :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, :dopri5, + :find_first_continuous_callback, :get_initial_values, :has_analytic, :has_jac, + :has_tgrad, :initialize_dae!, :max_vector_callback_length, :odex, :radau, + :radau5, :recursive_bottom_eltype, :rodas, :seulex, :solution_new_retcode, ) -# all_explicit_imports_are_public: SciMLBase initialization-algorithm internals. +# all_explicit_imports_are_public: SciMLBase initialization-algorithm internals, +# still non-public in SciMLBase 3.24. const EXPLICIT_IMPORTS_ARE_PUBLIC_IGNORE = ( :NoInit, :OverrideInit, :has_initialization_data, ) From fe316c1a636f908cac6294d429fe651e11d6521e Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 27 Jun 2026 00:32:57 -0400 Subject: [PATCH 4/6] QA: migrate SciMLBase-owned accesses + empty public-API EI ignores Now that the make-public releases are live (SciMLBase 3.27.0, DiffEqBase 7.6.0, SciMLTesting 1.7.0), finish the public-API ExplicitImports cleanup. - test/qa/Project.toml: bump SciMLTesting compat to "1.7" (gates the public-API EI checks to Julia >=1.11). - src/: rewrite `DiffEqBase.X` -> `SciMLBase.X` for the abstract types and solver-extension functions that SciMLBase owns (AbstractODEProblem, AbstractODEAlgorithm, AbstractODEIntegrator, AbstractParameterizedFunction, __solve, build_solution, has_jac/has_tgrad/has_analytic, calculate_solution_errors!, solution_new_retcode, initialize_dae!), so they are accessed through their owner. DiffEqBase-owned public names (apply_callback!/apply_discrete_callback!/CallbackCache/ find_first_continuous_callback/max_vector_callback_length/DefaultInit) keep their DiffEqBase.X access. - test/qa/qa.jl: empty the public-API ignore lists, then restore only the names still flagged on Julia 1.12 against the registered releases: SciMLBase-owned-but-private internals, DiffEqBase-owned-but-private (_process_verbose_param/Stats), recursive_bottom_eltype (RecursiveArrayTools) and SciMLStructures via the SciMLBase reexport, and the ODEInterface C-wrapper entry points/constants. The *_via_owners ignore list is left untouched. Verified: QA group 18/18 on Julia 1.12 (public-API checks run, 0 fail/ error/broken) and 16/16 on Julia 1.10 (public-API checks skipped); solve smoke test passes with __solve dispatch resolving to the migrated method. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- src/algorithms.jl | 2 +- src/initialize.jl | 14 +++++++------- src/integrator_types.jl | 2 +- src/solve.jl | 20 ++++++++++---------- test/qa/Project.toml | 2 +- test/qa/qa.jl | 36 ++++++++++++++++-------------------- 6 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/algorithms.jl b/src/algorithms.jl index 3acdb2e..c8420fd 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -1,6 +1,6 @@ # ODEInterface.jl Algorithms -abstract type ODEInterfaceAlgorithm <: DiffEqBase.AbstractODEAlgorithm end +abstract type ODEInterfaceAlgorithm <: SciMLBase.AbstractODEAlgorithm end abstract type ODEInterfaceImplicitAlgorithm <: ODEInterfaceAlgorithm end abstract type ODEInterfaceExplicitAlgorithm <: ODEInterfaceAlgorithm end """ diff --git a/src/initialize.jl b/src/initialize.jl index f88ffbd..ea85ada 100644 --- a/src/initialize.jl +++ b/src/initialize.jl @@ -11,7 +11,7 @@ export OverrideInit, NoInit, CheckInit, DefaultInit # DefaultInit: OverrideInit → CheckInit pattern (matching Sundials v5) # First run OverrideInit to compute consistent initial conditions, # then run CheckInit to verify the algebraic constraints are satisfied. -function DiffEqBase.initialize_dae!( +function SciMLBase.initialize_dae!( integrator::ODEInterfaceIntegrator, initializealg::DefaultInit ) @@ -19,7 +19,7 @@ function DiffEqBase.initialize_dae!( # First: OverrideInit to compute consistent initial conditions if has_initialization_data(prob.f) - DiffEqBase.initialize_dae!(integrator, OverrideInit()) + SciMLBase.initialize_dae!(integrator, OverrideInit()) # Check if OverrideInit failed if integrator.sol.retcode == ReturnCode.InitialFailure @@ -28,13 +28,13 @@ function DiffEqBase.initialize_dae!( end # Then: CheckInit to verify algebraic constraints are satisfied - DiffEqBase.initialize_dae!(integrator, CheckInit()) + SciMLBase.initialize_dae!(integrator, CheckInit()) return nothing end # NoInit: Do nothing, assume initial conditions are correct -function DiffEqBase.initialize_dae!( +function SciMLBase.initialize_dae!( integrator::ODEInterfaceIntegrator, initializealg::NoInit ) @@ -43,7 +43,7 @@ function DiffEqBase.initialize_dae!( end # CheckInit: Verify that initial conditions satisfy the algebraic constraints -function DiffEqBase.initialize_dae!( +function SciMLBase.initialize_dae!( integrator::ODEInterfaceIntegrator, initializealg::CheckInit ) @@ -69,7 +69,7 @@ function DiffEqBase.initialize_dae!( f(tmp, u0, p, t) # Check residuals of algebraic equations only - abstol = integrator.sol.prob isa DiffEqBase.AbstractODEProblem ? + abstol = integrator.sol.prob isa SciMLBase.AbstractODEProblem ? get(Dict(integrator.opts.callback.discrete_callbacks), :abstol, 1.0e-8) : 1.0e-8 # Try to get abstol from the solve options, fallback to default @@ -100,7 +100,7 @@ function DiffEqBase.initialize_dae!( end # OverrideInit: Use SciMLBase's initialization system (e.g., from ModelingToolkit) -function DiffEqBase.initialize_dae!( +function SciMLBase.initialize_dae!( integrator::ODEInterfaceIntegrator, initializealg::OverrideInit ) diff --git a/src/integrator_types.jl b/src/integrator_types.jl index d61afe9..9b0d2e6 100644 --- a/src/integrator_types.jl +++ b/src/integrator_types.jl @@ -9,7 +9,7 @@ mutable struct ODEInterfaceIntegrator{ F, algType, uType, uPrevType, oType, SType, solType, P, CallbackCacheType, } <: - DiffEqBase.AbstractODEIntegrator{algType, true, uType, Float64} + SciMLBase.AbstractODEIntegrator{algType, true, uType, Float64} f::F u::uType uprev::uPrevType diff --git a/src/solve.jl b/src/solve.jl index d3061f0..41a3281 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -1,5 +1,5 @@ -function DiffEqBase.__solve( - prob::DiffEqBase.AbstractODEProblem{uType, tuptType, isinplace}, +function SciMLBase.__solve( + prob::SciMLBase.AbstractODEProblem{uType, tuptType, isinplace}, alg::AlgType, timeseries = [], ts = [], ks = []; saveat = Float64[], @@ -19,8 +19,8 @@ function DiffEqBase.__solve( isstiff = alg isa ODEInterfaceImplicitAlgorithm warned = !isempty(kwargs) && check_keywords(alg, kwargs, warnlist) - if !(prob.f isa DiffEqBase.AbstractParameterizedFunction) && isstiff - if DiffEqBase.has_tgrad(prob.f) + if !(prob.f isa SciMLBase.AbstractParameterizedFunction) && isstiff + if SciMLBase.has_tgrad(prob.f) @SciMLMessage( "Explicit t-gradient given to this stiff solver is ignored.", verbose_spec, :mismatched_input_output_type @@ -77,7 +77,7 @@ function DiffEqBase.__solve( uprev = similar(u) - sol = DiffEqBase.build_solution( + sol = SciMLBase.build_solution( prob, alg, ts, _timeseries, timeseries_errors = timeseries_errors, calculate_error = false, @@ -112,7 +112,7 @@ function DiffEqBase.__solve( initialize_callbacks!(integrator) # DAE initialization - check/compute consistent initial conditions - DiffEqBase.initialize_dae!(integrator, initializealg) + SciMLBase.initialize_dae!(integrator, initializealg) # Check if initialization failed if integrator.sol.retcode == ReturnCode.InitialFailure @@ -164,7 +164,7 @@ function DiffEqBase.__solve( error("This solver must use full or banded mass matrices.") end end - if DiffEqBase.has_jac(prob.f) + if SciMLBase.has_jac(prob.f) dict[:JACOBIMATRIX] = (t, u, J) -> prob.f.jac(J, u, prob.p, t) end @@ -262,8 +262,8 @@ function DiffEqBase.__solve( return_retcode = ReturnCode.Success end - if DiffEqBase.has_analytic(prob.f) - DiffEqBase.calculate_solution_errors!( + if SciMLBase.has_analytic(prob.f) + SciMLBase.calculate_solution_errors!( integrator.sol; timeseries_errors = timeseries_errors, dense_errors = dense_errors @@ -282,7 +282,7 @@ function DiffEqBase.__solve( if haskey(stats, "no_lu_decomp") destats.nw = stats["no_lu_decomp"] end - return DiffEqBase.solution_new_retcode(sol, return_retcode) + return SciMLBase.solution_new_retcode(sol, return_retcode) end function save_value!(_timeseries, u, ::Type{T}, sizeu) where {T <: Number} diff --git a/test/qa/Project.toml b/test/qa/Project.toml index 3521e68..4123806 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -13,6 +13,6 @@ ODEInterfaceDiffEq = { path = "../.." } Aqua = "0.8" JET = "0.9,0.10,0.11" SafeTestsets = "0.0.1, 0.1" -SciMLTesting = "1.6" +SciMLTesting = "1.7" Test = "1" julia = "1.10" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 60690b2..e47b595 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -1,12 +1,6 @@ using SciMLTesting, ODEInterfaceDiffEq, Test using JET -# ExplicitImports ignore-lists. Every ignored name is a non-public name owned by a -# dependency (not by ODEInterfaceDiffEq): the standard SciML solver-extension surface -# (DiffEqBase/SciMLBase internals such as `__solve` / `initialize_dae!`) and the -# ODEInterface C-wrapper's non-public solver entry points. They become removable as the -# base libraries declare them `public`; until then they are legitimately ignored. - # all_qualified_accesses_via_owners: names accessed through DiffEqBase that SciMLBase # owns (DiffEqBase reexports them), plus SciMLStructures accessed through SciMLBase, and # recursive_bottom_eltype (RecursiveArrayTools-owned, accessed via SciMLBase reexport). @@ -17,25 +11,27 @@ const QUALIFIED_VIA_OWNERS_IGNORE = ( :initialize_dae!, :recursive_bottom_eltype, :solution_new_retcode, ) -# all_qualified_accesses_are_public: names still non-public in the registered releases -# (DiffEqBase 7, SciMLBase 3.24, ODEInterface 0.5). +# all_qualified_accesses_are_public: names still non-public in the registered releases. +# - SciMLBase-owned solver-extension internals (SciMLBase 3.27.0 still private). +# - recursive_bottom_eltype (RecursiveArrayTools-owned) / SciMLStructures +# (SciMLStructures-owned), accessed via the SciMLBase reexport: non-public there. +# - DiffEqBase-owned internals (DiffEqBase 7.6.0 still private). +# - ODEInterface C-wrapper solver entry points and constants (ODEInterface 0.5.1, no +# `public` declarations). const QUALIFIED_ARE_PUBLIC_IGNORE = ( - :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractODEProblem, - :AbstractParameterizedFunction, :CallbackCache, :OUTPUTFCN_CALL_REASON, + :AbstractODEIntegrator, :AbstractParameterizedFunction, :OUTPUTFCN_CALL_REASON, :OUTPUTFCN_CALL_STEP, :OUTPUTFCN_DENSE, :OUTPUTFCN_RET_CONTINUE, - :OUTPUTFCN_RET_CONTINUE_XCHANGED, :OUTPUTFCN_WODENSE, :OptionsODE, - :RHS_CALL_INSITU, :SciMLStructures, :Stats, :__solve, :_process_verbose_param, - :alg_order, :apply_callback!, :apply_discrete_callback!, :build_solution, - :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, :dopri5, - :find_first_continuous_callback, :get_initial_values, :has_analytic, :has_jac, - :has_tgrad, :initialize_dae!, :max_vector_callback_length, :odex, :radau, - :radau5, :recursive_bottom_eltype, :rodas, :seulex, :solution_new_retcode, + :OUTPUTFCN_RET_CONTINUE_XCHANGED, :OUTPUTFCN_WODENSE, :OptionsODE, :RHS_CALL_INSITU, + :SciMLStructures, :Stats, :__solve, :_process_verbose_param, + :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, :dopri5, :has_analytic, + :has_tgrad, :initialize_dae!, :odex, :radau, :radau5, :recursive_bottom_eltype, + :rodas, :seulex, :solution_new_retcode, ) -# all_explicit_imports_are_public: SciMLBase initialization-algorithm internals, -# still non-public in SciMLBase 3.24. +# all_explicit_imports_are_public: SciMLBase initialization-system internal, still +# non-public in SciMLBase 3.27.0. const EXPLICIT_IMPORTS_ARE_PUBLIC_IGNORE = ( - :NoInit, :OverrideInit, :has_initialization_data, + :has_initialization_data, ) run_qa( From d6e9548d39244541ff505a57784964289a6ef3e6 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 28 Jun 2026 06:04:28 -0400 Subject: [PATCH 5/6] QA: trim now-public ExplicitImports ignores Co-Authored-By: Chris Rackauckas --- test/qa/qa.jl | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/test/qa/qa.jl b/test/qa/qa.jl index e47b595..fb41c6c 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -12,34 +12,26 @@ const QUALIFIED_VIA_OWNERS_IGNORE = ( ) # all_qualified_accesses_are_public: names still non-public in the registered releases. -# - SciMLBase-owned solver-extension internals (SciMLBase 3.27.0 still private). +# - SciMLBase-owned solver-extension internals (SciMLBase 3.28.1 still private). # - recursive_bottom_eltype (RecursiveArrayTools-owned) / SciMLStructures # (SciMLStructures-owned), accessed via the SciMLBase reexport: non-public there. # - DiffEqBase-owned internals (DiffEqBase 7.6.0 still private). # - ODEInterface C-wrapper solver entry points and constants (ODEInterface 0.5.1, no # `public` declarations). const QUALIFIED_ARE_PUBLIC_IGNORE = ( - :AbstractODEIntegrator, :AbstractParameterizedFunction, :OUTPUTFCN_CALL_REASON, - :OUTPUTFCN_CALL_STEP, :OUTPUTFCN_DENSE, :OUTPUTFCN_RET_CONTINUE, - :OUTPUTFCN_RET_CONTINUE_XCHANGED, :OUTPUTFCN_WODENSE, :OptionsODE, :RHS_CALL_INSITU, - :SciMLStructures, :Stats, :__solve, :_process_verbose_param, - :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, :dopri5, :has_analytic, - :has_tgrad, :initialize_dae!, :odex, :radau, :radau5, :recursive_bottom_eltype, + :OUTPUTFCN_CALL_REASON, :OUTPUTFCN_CALL_STEP, :OUTPUTFCN_DENSE, + :OUTPUTFCN_RET_CONTINUE, :OUTPUTFCN_RET_CONTINUE_XCHANGED, :OUTPUTFCN_WODENSE, + :OptionsODE, :RHS_CALL_INSITU, :SciMLStructures, :Stats, :__solve, + :_process_verbose_param, :calculate_solution_errors!, :ddeabm, :ddebdf, :dop853, + :dopri5, :initialize_dae!, :odex, :radau, :radau5, :recursive_bottom_eltype, :rodas, :seulex, :solution_new_retcode, ) -# all_explicit_imports_are_public: SciMLBase initialization-system internal, still -# non-public in SciMLBase 3.27.0. -const EXPLICIT_IMPORTS_ARE_PUBLIC_IGNORE = ( - :has_initialization_data, -) - run_qa( ODEInterfaceDiffEq; explicit_imports = true, ei_kwargs = (; all_qualified_accesses_via_owners = (; ignore = QUALIFIED_VIA_OWNERS_IGNORE), all_qualified_accesses_are_public = (; ignore = QUALIFIED_ARE_PUBLIC_IGNORE), - all_explicit_imports_are_public = (; ignore = EXPLICIT_IMPORTS_ARE_PUBLIC_IGNORE), ), ) From 8147d51e2c9c3ff85d9c4be4a4b19097ac86bc92 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 28 Jun 2026 10:27:58 -0400 Subject: [PATCH 6/6] QA: thorough EI ignore re-clean (drop stale incl via_owners, migrate non-public re-exports) Co-Authored-By: Chris Rackauckas --- test/qa/qa.jl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/qa/qa.jl b/test/qa/qa.jl index fb41c6c..23eb4ec 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -1,14 +1,11 @@ using SciMLTesting, ODEInterfaceDiffEq, Test using JET -# all_qualified_accesses_via_owners: names accessed through DiffEqBase that SciMLBase -# owns (DiffEqBase reexports them), plus SciMLStructures accessed through SciMLBase, and -# recursive_bottom_eltype (RecursiveArrayTools-owned, accessed via SciMLBase reexport). +# all_qualified_accesses_via_owners: names accessed via SciMLBase that SciMLBase does +# not own. SciMLStructures (the SciMLStructures-owned module) and recursive_bottom_eltype +# (RecursiveArrayTools-owned) are both reached through the SciMLBase reexport. const QUALIFIED_VIA_OWNERS_IGNORE = ( - :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractODEProblem, - :AbstractParameterizedFunction, :SciMLStructures, :__solve, :build_solution, - :calculate_solution_errors!, :has_analytic, :has_jac, :has_tgrad, - :initialize_dae!, :recursive_bottom_eltype, :solution_new_retcode, + :SciMLStructures, :recursive_bottom_eltype, ) # all_qualified_accesses_are_public: names still non-public in the registered releases.