Fix Julia 1.12: replace Cassette with code_typed-based branch detection#55
Merged
ChrisRackauckas merged 2 commits intoJun 13, 2026
Conversation
Julia 1.12 requires generated functions to return `CodeInfo`, not `Expr` (see `Base.generated_body_to_codeinfo`). Cassette v0.3.14 does not yet implement this change, so all `overdub` calls fail at runtime on 1.12. Replace the entire Cassette machinery with a direct `code_typed` call: - `code_typed(f, argtypes; optimize=false)` gives type-inferred but unoptimized IR, which is exactly what the pass was inspecting before. - Scanning the resulting `CodeInfo` for `GotoIfNot` nodes reproduces the original semantics: value-dependent `if`/`?:` produce `GotoIfNot`, `ifelse()` does not, and stdlib iteration/boundscheck branches stay inside their callees and are invisible at the user-function level. - The `is_leaf(f, args...) = false` dispatch replaces the Cassette `overdub` extension point. Users who previously added an `overdub` specialization now add `FunctionProperties.is_leaf(::typeof(f)) = true`. Remove `Cassette` and `DiffRules` from deps entirely (no deps remain). Bump version to 0.1.4. All tests pass on Julia 1.10 and 1.12. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Indent the body of the `if GROUP in ("All", "Core")` block, which PR SciML#53
introduced without indentation. Runic v1.7 (run in CI via FormatCheck)
requires it.
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
ChrisRackauckas
added a commit
that referenced
this pull request
Jun 13, 2026
PR #55 exported `is_leaf` with a docstring but did not reference it in the manual, so Documenter's `:missing_docs` check now fails on main. Add `is_leaf` to the API reference, and replace the outdated "uses Cassette internally" section with a description of the `code_typed`-based branch detection. Verified locally: `julia --project=docs docs/make.jl` builds cleanly. Co-authored-by: Chris Rackauckas (Claude) <accounts@chrisrackauckas.com>
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.
Problem
Julia 1.12 changed generated functions to require
CodeInforeturn values instead ofExpr(see changelog). Cassette v0.3.14 does not implement this change, so every call tohasbranchingfails on 1.12 with:This is an upstream Cassette limitation with no imminent fix.
Solution
Remove the Cassette dependency entirely and replace the IR-pass approach with a direct
code_typedcall:code_typed(...; optimize=false)gives type-inferred but unoptimized IR — exactly the same level Cassette's pass was inspecting. The semantics are preserved:x < 0 ? -x : x→GotoIfNotin IR →trueifelse(x < 0, -x, x)→ function call, noGotoIfNot→falsetrue ? 1 : 0→GotoIfNotin unoptimized IR →true(constant folding only happens atoptimize=true)x1, x2 = xdestructuring →GotoIfNotstays insideiterate, invisible at the caller level →falseBreaking change: extension API
The
Cassette.overdubspecialization pattern is replaced byis_leafdispatch:Changes
src/FunctionProperties.jl: 170 lines → 45 lines; no depsProject.toml: dropCassetteandDiffRulesdeps; bump to v0.1.4test/runtests.jl: update extension example to useis_leafAll tests pass on Julia 1.10 and 1.12.