Repository navigation
Fix CI on Julia 1.13 and nightly - #847
Merged
Merged
Conversation
- `@gpu` test helper: splice the name `_gpu_test` instead of the function value. Since Julia 1.13.0-DEV.300 (JuliaLang/julia#57839) `@test` lowers to `eval_test_function(..., quoted_func::Union{Expr,Symbol}, ...)`, so every `@gpu` test errored with a `MethodError`. - `_matfun`: real-valued functions of `Hermitian{<:Real}` return `Hermitian` since Julia 1.12.0-DEV.1322 (JuliaLang/julia#55951); match the primal type. - Mark `Threads._spawn_set_thrpool` non-differentiable (hit by `Threads.@spawn` in Zygote on Julia 1.13). - Test-only compat: `JuliaInterpreter = "0.9, 0.12"`; 0.9 no longer precompiles on nightly. - Workflows: run on pushes to `main` (was `master`, which doesn't exist). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Test-only compat: `JLArrays = "0.1, 0.4"`. With `@gpu` tests running again, GPUArrays 10 (JLArrays 0.1) hits scalar indexing in Julia >= 1.12 LinearAlgebra (`tr(::StridedMatrix)`, 3x3 `matmul3x3!`, Diagonal `mul!`); GPUArrays 12.1 (JLArrays 0.4) overrides these. - Tests: avoid `@eval using`/`@eval struct` inside interpreted testsets. JuliaInterpreter 0.12 respects world age, so those bindings were invisible. - `sortslices` rrule: don't capture the index tuple, whose type depends on the value of `dims`; the rrule is now inferrable. - broadcast.jl: vararg `*` broadcast works on GPU since Julia 1.13 (still broken on 1.6, 1.10, 1.11, 1.12). - `normalize` rrules: replace `LinearAlgebra.__normalize!`, removed in JuliaLang/LinearAlgebra.jl#1634, by a local copy of the upstream logic. - structured.jl: skip `Adjoint(::Adjoint)`/`Transpose(::Transpose)` where they throw (JuliaLang/LinearAlgebra.jl#1739). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…s 0.4 Since JuliaLang/LinearAlgebra.jl#1359 (Julia 1.13.0-DEV.887), `exp` and positive semi-definite `sqrt` of `Hermitian`/`Symmetric` matrices are computed as `(U * √D) * (U * √D)'`, so `_matfun` no longer reproduced `f(A)` exactly. JLArrays 0.4 implements `reverse` without scalar indexing, so the `@gpu_broken` tests passed unexpectedly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JuliaInterpreter 0.12 fails on the new `foreigncall` form and looks up
methods with `Type{T}` instead of `Core.TypeEgal{T}` signatures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With JuliaLang/LinearAlgebra.jl#1529, triangular solves throw for zero diagonal entries, so the `lu!` frule failed for singular A with `check=false` on Julia 1.14. For square and wide A the rules now only invert the leading (q-1)×(q-1) block of U, so they compute the derivative, which exists if only the last pivot is zero. Otherwise, the factors are not differentiable and the rules return NaN. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
- `sortslices` rules: factor out the thrice-repeated index tuple. - `normalize` tests: cover the subnormal-norm branch of `_normalize!`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This was referenced Oct 16, 2026
Closed
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.
CI has been failing on every PR since early 2026: GitHub's
julia: 1now resolves to Julia 1.13, and nightly to 1.14-DEV. Root causes, each traced to an upstream change:1. All
@gputests error on Julia ≥ 1.13.0-DEV.300 (224 errors)_gpu_macrospliced the function value_gpu_testinto the@testcall. Since JuliaLang/julia#57839 (d934b032ea5b, 1.13.0-DEV.300),@test f(args...)lowers toTest.eval_test_function(f, args, kwargs, quoted_func::Union{Expr,Symbol}, …), so every@gputest threw aMethodError(the CI log shows "Test threw exception" with no message). The fix splices the name instead.2. GPU tests need JLArrays 0.4 (supersedes #846)
Once the
@gputests actually run,muladd(3×3),Diagonal * Matrix, andtrhit "Scalar indexing is disallowed" on 1.13. JLArrays 0.1 caps GPUArrays at 10.3.1, which predates Julia ≥ 1.12's LinearAlgebra changes:tr(::StridedMatrix)scalar loop, the 2×2/3×3matmul3x3!path, and Diagonalmul!. GPUArrays 12.1 (JLArrays 0.4.2) overrides these. Compat is nowJLArrays = "0.1, 0.4"(Julia 1.6 still resolves 0.1).The vararg
*broadcast@gpu_brokentest now passes on 1.13. Checked locally: it is still broken on 1.6, 1.10, 1.11, and 1.12, and passes on 1.13 with both GPUArrays 10.3.1 and 12.1.0. It's now gated onVERSION >= v"1.13".JLArrays 0.4 also implements
reversewithout scalar indexing, so thereverse@gpu_brokentests now pass with it. They're gated onparentmodule(reverse, Tuple{JLArray{Float32,1}}) !== Base.3. Matrix functions of
Hermitian{<:Real}(194 failures)Since JuliaLang/julia#55951 (
4d2184159b15, 1.12.0-DEV.1322), real-valuedf(::Hermitian{<:Real})returnsHermitian, notSymmetric._matfunnow matches the primal type under that exact version bound. All 15 matrix-function rules andsincosgo through_matfun, so this is the single place to change. The equivalent test gate lives in one helper. This supersedes #840/#833.Since JuliaLang/LinearAlgebra.jl#1359 (
44b6bc177f, 1.13.0-DEV.887),expand positive semi-definitesqrtare computed as(U * √D) * (U * √D)', not asU * D * U'. The primal then differed fromf(A)by roundoff (36Y_ad == Yfailures)._matfunnow reproduces Base's computation exactly. Checked locally: the primal is bitwise identical tof(A)for all 15 functions on 1.6, 1.12, 1.13 and 1.14-DEV.4. Zygote integration (
Threads.@spawn)On 1.13,
Threads.@spawncallsThreads._spawn_set_thrpool(::Task, ::Symbol), which wraps a foreigncall that Zygote can't differentiate. It's now marked@non_differentiable(guarded withisdefined, following the existing pattern innondiff.jl). Verified by the IntegrationTest/Zygote job: thestructures.jlforeigncall errors are gone. A guarded test inbase.jlchecks that the rule is defined.5. JuliaInterpreter: nightly precompile crash, plus world age
JuliaInterpreter 0.9.46 (capped by the test-only compat
0.8,0.9) fails to precompile on 1.14-DEV. Compat is now"0.9, 0.12": only the minors CI actually resolves (1.6 → 0.9.x, 1.13/nightly → 0.12).JuliaInterpreter 0.12 respects world age, which exposed two things:
@eval using …/@eval struct …inside an interpreted@testsetcouldn't see the new bindings. They now use local bindings or a top-levelstruct.sortslicesrrule was never inferrable; 0.9 hid this. Its pullback captured an index tuple whose type depends on the value ofdims, and it now rebuilds that tuple inside the pullback (via a_sortslices_indshelper shared with the frule).6. Upcoming LinearAlgebra changes (nightly)
LinearAlgebra.__normalize!was removed in fix normalize and normalize! JuliaLang/LinearAlgebra.jl#1634. Thenormalizerrules now use a local copy of the current upstreamnormalize!logic, reusing the precomputed norm. It is bitwise identical tonormalizeon nightly. On older Julia it differs only by a few ulp for complex inputs with subnormal norm. New tests cover the subnormal-norm branch.Adjoint(::Adjoint)/Transpose(::Transpose)now throw (Disallow double wrap withAdjointorTransposeJuliaLang/LinearAlgebra.jl#1739). Those test cases are skipped where the double wrap is not allowed.7. Workflows never ran on
mainCI,IntegrationTest, andJuliaNightlytriggered onpush: branches: [master], but the default branch ismain.8. Testsets run compiled on Julia 1.14 (nightly)
JuliaInterpreter 0.12.0 (latest release) doesn't support 1.14-DEV. It fails on a new
foreigncallform ("ccall function name tuple can have at most 2 elements"; 1420 errors per job). It also looked up methods withType{T}signatures, so it missed rules that ChainRulesCore's macros defined withCore.TypeEgal{T}self-types:rrule(Float64, 1.2)returnednothingwhen interpreted. ChainRulesCore 1.26.2 (JuliaDiff/ChainRulesCore.jl#714) usesType{T}again, but theforeigncallfailure remains. OnVERSION >= v"1.14.0-DEV"the testsets now run compiled.9.
lurules for singular matricesSince JuliaLang/LinearAlgebra.jl#1529 (Julia 1.14), BLAS triangular solves throw on a zero diagonal. On ≤ 1.13 they returned
Inf/NaN. So thelu!frule threw aSingularExceptionfor singular A withcheck=false, because it divided by all of U.For square and wide A, the factors are differentiable as long as only the last pivot is zero. The rules computed
L \ (P * ΔA) / U, which usesU[q, q]even though the derivative doesn't depend on it.lupullback now share one branch that only inverts the leading (q-1)×(q-1) block of U. This gives the correct derivative when the last pivot is zero.NaN, matching the previous behaviour withcheck=false. That's an earlier zero pivot, which makes L discontinuous, or a zero last pivot of tall A.F.infogives the index of the first zero pivot. It is negated for unpivoted LU since LU factorization: add allowsingular keyword argument JuliaLang/julia#52957, so the rules negate it back under the version bound 1.11.0-DEV.1535.Compared with master, the new rules have the same allocations and are within ±7% of its speed (n = 10 to 500). They're slightly more accurate against a BigFloat reference.
New tests run
test_frule/test_rruleat matrices whose last pivot is exactly zero: square and wide shapes,RowMaximumandNoPivot. The test matrices use dyadic L with |L[i, j]| < 1 and power-of-two pivots, so LAPACK factors them exactly. Further tests check forNaNon tall A with a zero last pivot and onzeros(n, n). The existingcheck=falserrule test never ran the pullback, because its tangent had nofactors.Known remaining failures (not fixable here)
gradcheck_p2.jlhard-codes@test … broken = VERSION >= v"1.12" && MT <: Hermitian{Float64}for matrix functions andsincos. With fix 3 these now pass, so they report 17 "Unexpected Pass". Zygote needs to drop thosebrokenflags.JuliaNightly is green: the 1.14
ambiguitiesfailure (@non_differentiable Array(::AbstractArray{Bool})vsrrule(::Type{Array}, ::HermOrSym), JuliaDiff/ChainRulesCore.jl#713) is fixed in ChainRulesCore 1.26.2.Version bumped to 1.73.1.
🤖 Generated with Claude Code
Closes #840. Closes #833. Closes #842. Closes #845. Closes #846. Closes #828. Closes #817.