Skip to content

QA: scan the Enzyme and Mooncake extensions - #82

Merged
ChrisRackauckas merged 1 commit into
SciML:mainfrom
ChrisRackauckas-Claude:qa-check-extensions
Aug 1, 2026
Merged

QA: scan the Enzyme and Mooncake extensions#82
ChrisRackauckas merged 1 commit into
SciML:mainfrom
ChrisRackauckas-Claude:qa-check-extensions

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member

Please ignore this PR until it has been reviewed by @ChrisRackauckas.

What this fixes

run_qa runs ExplicitImports' checks over the package module and its submodules.
ExplicitImports does know about extensions — it reads the [extensions] table
out of Project.toml — but it skips any extension for which
Base.get_extension(mod, ext) returns nothing, and an extension module only
exists once its triggers are loaded. The QA environment loaded no weakdeps, so
neither FunctionWrappersWrappersEnzymeExt nor
FunctionWrappersWrappersMooncakeExt was being checked at all.

Adding Enzyme, EnzymeCore and Mooncake to test/qa/Project.toml (compat
mirroring the root Project.toml) and using them in test/qa/qa.jl puts both
extensions under QA.

Coverage

  • Now scanned: FunctionWrappersWrappersEnzymeExt, FunctionWrappersWrappersMooncakeExt.
  • Left out: nothing. All three weakdeps are pure-Julia and resolve in the QA
    environment, so there are no remaining unscanned extensions.

Fixed at the source (not ignored)

no_implicit_imports flagged the Enzyme extension for relying on using Enzyme
/ using EnzymeCore / using EnzymeCore.EnzymeRules and then referring to
Enzyme, EnzymeCore, EnzymeRules, Const, Duplicated, BatchDuplicated,
Forward, ForwardWithPrimal. Those became explicit imports:

using Enzyme: Enzyme
using EnzymeCore: EnzymeCore, BatchDuplicated, Const, Duplicated, Forward, ForwardWithPrimal
using EnzymeCore.EnzymeRules: EnzymeRules

EnzymeRules is imported from the submodule that owns it rather than from
EnzymeCore (which does not export it), and the three inactive_type
definitions now go through EnzymeRules.inactive_type instead of the
EnzymeCore.EnzymeRules.inactive_type path. Side benefit: this removes the two

WARNING: both EnzymeRules and Enzyme export "runtime_activity"; uses of it in module FunctionWrappersWrappersEnzymeExt must be qualified
WARNING: both EnzymeRules and Enzyme export "tape_type"; ...

warnings that were printed every time the extension loaded.

The Mooncake extension needed no source changes.

Ignore entries added

All of these are AD rule-authoring interfaces: the names a package must use to
teach an AD backend about a new callable, which the backend documents but has not
declared public. There is no public spelling for any of them.

all_qualified_accesses_are_public:

Symbol Owner Why unavoidable
forward, augmented_primal, reverse, inactive_type, strong_zero EnzymeCore.EnzymeRules The generic functions a rule author adds methods to. EnzymeRules exports the config accessors (needs_primal, overwritten, runtime_activity, ...) but not these extension points.
build_rrule, rrule!!, tangent_type, primal Mooncake Mooncake declares only its top-level entry points public (value_and_gradient!!, prepare_gradient_cache, Config, Dual, ...); the entire rule API is documented-but-not-public.
Typeof Core Standard idiom for building a call-signature tuple type; typeof is wrong for arguments that are themselves types, and there is no Base equivalent.

all_explicit_imports_are_public: @is_primitive, CoDual, MinimalCtx,
NoRData, NoTangent, fdata, zero_tangent — same Mooncake rule API as above.

The pre-existing :FunctionWrapper ignore is unchanged. No check was disabled and
nothing was marked broken.

Local runs

QA on the LTS (Julia 1.10.11) — the two public-API checks are skipped there by
SciMLTesting:

Test Summary: | Pass  Total     Time
QA            |   18     18  1m01.3s
     Testing FunctionWrappersWrappers tests passed

QA on Julia 1.12.6, where all_qualified_accesses_are_public and
all_explicit_imports_are_public also run:

Test Summary: | Pass  Total     Time
QA            |   20     20  3m40.6s
     Testing FunctionWrappersWrappers tests passed

Because the Enzyme extension's source changed, both AD groups were re-run on 1.10:

Test Summary: | Pass  Total   Time
Enzyme        |   68     68  35.1s
     Testing FunctionWrappersWrappers tests passed

Test Summary: | Pass  Total   Time
Mooncake      |   13     13  10.3s
     Testing FunctionWrappersWrappers tests passed

Runic 1.7.0 reports the touched files clean. No Manifest.toml is committed.

ExplicitImports only analyzes an extension module when `Base.get_extension`
returns it, which requires the extension's triggers to be loaded. The QA
environment loaded no weakdeps, so neither `FunctionWrappersWrappersEnzymeExt`
nor `FunctionWrappersWrappersMooncakeExt` was checked at all.

Add Enzyme, EnzymeCore and Mooncake to `test/qa/Project.toml` (compat mirroring
the root Project.toml) and `using` them in `qa.jl`. Both extensions are now
covered.

The new findings in the Enzyme extension are fixed at the source rather than
ignored: the blanket `using Enzyme` / `using EnzymeCore` /
`using EnzymeCore.EnzymeRules` become explicit imports, and the
`inactive_type` definitions go through `EnzymeRules` directly instead of the
`EnzymeCore.EnzymeRules` path. This also drops the two "both EnzymeRules and
Enzyme export ..." ambiguity warnings emitted when the extension loaded.

The remaining findings are AD rule-authoring interfaces with no public
spelling (EnzymeRules' extension points, Mooncake's rule API) plus
`Core.Typeof`, and are ignored with a comment naming the owner.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas
ChrisRackauckas marked this pull request as ready for review August 1, 2026 08:53
@ChrisRackauckas
ChrisRackauckas merged commit 8616e04 into SciML:main Aug 1, 2026
6 checks passed
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.

2 participants