Pin ModelingToolkit's public reexport surface - #4881
Draft
ChrisRackauckas-Claude wants to merge 1 commit into
Draft
Pin ModelingToolkit's public reexport surface#4881ChrisRackauckas-Claude wants to merge 1 commit into
ChrisRackauckas-Claude wants to merge 1 commit into
Conversation
This was referenced Aug 5, 2026
`run_qa`'s `No unapproved public reexports` check reported 487 findings. `ModelingToolkit` exposes those names publicly but owns none of them: they arrive through `@reexport using ModelingToolkitBase` (339 names), which itself `@reexport`s Symbolics (83) and, transitively, SymbolicUtils (32) and TermInterface (4), plus the SciMLBase problem types (19) and a handful from CommonSolve/JumpProcesses/BipartiteGraphs/ModelingToolkitTearing/StateSelection/ UnPack. A blanket reexport cannot distinguish "we mean to expose this" from "a dependency happened to add a public binding", so the audit flags all of them. `REEXPORTED_API` in `test/qa/qa.jl` records the set as approved, grouped by owner with the reason each group is intentional. Pinning it is the point: it is version-controlled, so a dependency adding a new public name now fails this test instead of silently widening ModelingToolkit's API surface. `@reexport using Symbolics` and `@reexport using UnPack` are dropped from `src/ModelingToolkit.jl`: ModelingToolkitBase already re-exports both, and ModelingToolkit `@reexport`s ModelingToolkitBase, so they only duplicated an existing surface. `public_reexports(ModelingToolkit)` returns the same 487 names before and after, verified by diffing the two lists. One entry is an accidental leak rather than a deliberate export: `find_solvables!` is a StateSelection internal that `StructuralTransformations` `export`s but only ever calls qualified. It is listed with a comment; removing it is breaking and belongs in a major release, not here. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
ChrisRackauckas-Claude
force-pushed
the
agent/qa-reexports
branch
from
August 7, 2026 20:21
3d94fe0 to
01baec6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ignore until reviewed by @ChrisRackauckas.
Stacked on #4880 — review that one first; this branch contains its commit.
Problem
On unmodified
master(32a955a),run_qa'sNo unapproved public reexportscheck fails with 487 findings.ModelingToolkitexposes all of these publicly and owns none of them:@reexport using ModelingToolkitBase+@import_mtkbase@reexport using Symbolicsinside ModelingToolkitBaseRewriters,Code)@reexport using UnPackA blanket reexport cannot distinguish "we mean to expose this" from "a dependency happened to add a public binding", which is exactly what the audit is complaining about.
Change
REEXPORTED_APIintest/qa/qa.jlrecords the approved set, grouped by owner, each group carrying the reason it is intentional. This is the value the check exists to protect: the set is now version-controlled, so a dependency adding a new public name fails this test rather than silently widening ModelingToolkit's API, and every addition to the surface becomes a deliberate decision. Removing an entry is a breaking change.@reexport using Symbolicsand@reexport using UnPackare dropped fromsrc/ModelingToolkit.jl. ModelingToolkitBase already re-exports both and ModelingToolkit@reexports ModelingToolkitBase, so these two lines only duplicated a surface that already existed.One entry is called out as an accidental leak rather than a deliberate export:
find_solvables!is a StateSelection internal thatStructuralTransformationsexports but only ever calls qualified (StateSelection.find_solvables!). It is listed with a comment; dropping it is a breaking change and belongs in a major release, not a QA fix.What this PR does not do
It does not shrink the surface. Trimming the names nobody uses (the
sympy_*family, the Laplace/Groebner helpers,@makearray,print_ir, …) removes public API and therefore requires a major version bump, and I could not validate the removals without running the full ModelingToolkit + Catalyst + ModelingToolkitStandardLibrary suites. The pinned list makes that a tractable follow-up: the candidates are exactly the entries in the Symbolics/SymbolicUtils groups with no use site indocs/,test/, Catalyst.jl or ModelingToolkitStandardLibrary.jl.Verification
Run against this branch on Julia 1.11, replicating
run_qa's logic (public_reexports(pkg; allow = reexports_allow)), plus a stale-entry check thatrun_qadoes not do:The reexport removal in
src/ModelingToolkit.jlleaves the surface byte-identical —public_reexports(ModelingToolkit)was dumped before and after and diffed:Smoke test on this branch (Lorenz
mtkcompile+solve(Rodas5P()), index-3 pendulummtkcompile,linearization_function/linearize):🤖 Generated with Claude Code
https://claude.ai/code/session_019ywCW8vbGoc9X3dUbmXyme