Skip to content

Proposal: Tagging API#815

Open
longemen3000 wants to merge 11 commits into
JuliaDiff:masterfrom
longemen3000:maketag
Open

Proposal: Tagging API#815
longemen3000 wants to merge 11 commits into
JuliaDiff:masterfrom
longemen3000:maketag

Conversation

@longemen3000

@longemen3000 longemen3000 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

This PR proposes a Tagging API. the main objective is to provide external ForwardDiff users a way to control tag generation and comparison. The API is composed of:

  • AbstractTag{F,V}: Abstract type for all tags following the Tagging API.
  • maketag(f::F,::Type{V}): generates an instance of a tag, given an instance of a function f and a element type V will generate a tag that follows the tag API.

Some invariants:

  • All tags are defined as a combination of a "callable" type f and a element type V.
  • V should be a number (not enforced at the AbstractTag level, i don't know if any package does something weird here)
  • dispatch for custom tags is done via dispatching on f::F, where f should behave according to the context it was used
  • two tag types can be compared by the combination of the callable type and the element type. If they have the same callable type and the same element type, they are considered equal for the purposes of tag comparison.

Note that the invariants above do not imply that maketagtype(f::F,::Type{V}) == MyTag{F,V}. For example, F could have additional information about closed-over variables that we want to move over to V.

One application for this API is to create a StaticTag type that does comparisons via inspecting the fields of the closures (like what's proposed in #807), or for a HashedTag type (like what was tried in #748). More importantly, experimenting with new tag types can be done in external packages, instead of PRs to ForwardDiff.

Closes #813

Any comments are really appreciated.

@devmotion

Copy link
Copy Markdown
Member

for a HashedTag type (like what was tried in #748)

Apparently that approach is completely unsound: #748 (comment)

@longemen3000

Copy link
Copy Markdown
Contributor Author

Yes, that particular PR was unsound, but there are more options for tags defined at runtime, if someone wants to give it a try (one of the alternatives in #807 was via objectid)

@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.58824% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.25%. Comparing base (777420f) to head (ecacc26).

Files with missing lines Patch % Lines
src/config.jl 28.57% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #815      +/-   ##
==========================================
- Coverage   90.74%   90.25%   -0.49%     
==========================================
  Files          11       11              
  Lines        1070     1078       +8     
==========================================
+ Hits          971      973       +2     
- Misses         99      105       +6     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@longemen3000

Copy link
Copy Markdown
Contributor Author

tests are finally passing (except for pre, because of JET version incompatibility)

@devmotion

Copy link
Copy Markdown
Member

I think the motivation for this change is missing and its design is unclear without clearly designed alternative tagging systems. Without such it's also not clear to me whether this would solve any actual problems and whether eg combinations of different tagging systems would create new problems.

@longemen3000

longemen3000 commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

I think the motivation for this change is missing and its design is unclear without clearly designed alternative tagging systems.

The main motivation for this PR is to allow experimenting with alternative tag designs. #748 is closed and #807 is stalled in its current form. For a proof of concept, i made an alternative tagging system, based on #807 (comment) along with a closure workaround
https://github.com/ClapeyronThermo/Clapeyron.jl/tree/AD-custom-tags/lib/StaticForwardDiffTags

That tag system in particular takes the tradeoff of a more cumbersome function definition in exchange of faster compile times; while the package itself does not have tests, the branch is used as AD provider for Clapeyron.jl, where we use up to 4th order nested duals for some functions.
Most of the overloads of that package are just changing the hardcoded Tag in ForwardDiff functions for maketagtype.

whether eg combinations of different tagging systems would create new problems.

On the interaction between two tagging systems, and in particular, the interaction of a external tagging system and the current ForwardDiff.Tag, I see no other option that just register new tags (with the same types) and fallback to tagcount.
Another, more restrictive option would be to just block two tags systems from interacting. (probably useful if one wants to be sure that no code result is determined at runtime, like what tagcount does

(the extension code is broken at the moment if you want to load it as a standalone package, but the rest should work)

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.

tagging API?

2 participants