SciML / SciML/SimpleDiffEq.jl

JET typo-mode: 36 reports on Julia 1.12 (1 real Euler-interp bug + ~35 correlated-branch may-be-undefined)

Open
#123 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Julia
Stars
23
Forks
13
Avg merge
5h 16m
Merged PRs (30d)
9

Description

JET report_package(; mode = :typo) findings on Julia 1.12 (JET 0.11.x)

When the QA group runs the standard SciML JET typo check
(JET.test_package(SimpleDiffEq; target_modules = (SimpleDiffEq,), mode = :typo),
now enabled via run_qa in SciMLTesting 1.6) it is clean on Julia 1.10/1.11
(JET 0.9.x) but reports 36 possible errors on Julia 1.12 (JET 0.11.x). The
source is byte-identical to master, so these predate the QA-conversion PR
(#122) — the conversion merely turned the JET check on.

Reproduce
# in test/qa (SciMLTesting 1.6.0, JET resolves to 0.11.x on Julia 1.12)
using SimpleDiffEq, JET
rep = JET.report_package(SimpleDiffEq; target_modules = (SimpleDiffEq,), mode = :typo)
length(JET.get_reports(rep))   # 0 on 1.10/1.11, 36 on 1.12
The 36 findings, by category

1. One genuine latent bug (local variable u is not defined)
src/euler/euler.jl:199, in the in-place branch of the SimpleEulerIntegrator
interpolant:

else
    for i in 1:length(u)             # reads `u` before it is ever assigned
        u = @. (1 - Θ) * y₀ + Θ * y₁
    end
    return u
end

u is only bound inside the loop body, but length(u) reads it first — this
path throws UndefVarError if exercised. (Likely length(u) should be
length(y₁), and the in-place branch should write into a preallocated buffer
rather than rebind u.)

2. ~35 may be undefined reports on correlated-branch control flow
These are correct code that JET 0.9 could prove safe but JET 0.11 cannot,
because the guard that guarantees the binding lives in a separate if block:

  • q11 in the adaptive step! error-estimate blocks
    (src/tsit5/atsit5.jl:293,378,546,676, src/tsit5/gpuatsit5.jl:278,
    src/verner/gpuvern7.jl:407, src/verner/gpuvern9.jl:575): q11 is bound only
    in the else of if iszero(EEst), then used under if EEst > 1. When
    EEst > 1, EEst is nonzero, so the else ran and q11 is bound.
  • cur_t in the saveat save loops
    (src/tsit5/atsit5.jl:150,152,154,156, src/tsit5/gpuatsit5.jl:110,111,114,120,296,297,300,306,
    src/verner/gpuvern7.jl:138,139,207,216,425,426,499,508,
    src/verner/gpuvern9.jl:185,186,316,327,593,594,739,750): cur_t is bound only
    in the else of if saveat === nothing, then used under elseif saveat !== nothing.
Mitigation in place

test/qa/qa.jl marks the JET check jet_broken on Julia 1.12+ only
(jet_broken = VERSION >= v"1.12"), so the QA lane records Broken (green) while
these stand, and the still-clean 1.10/1.11 lanes keep running the hard
test_package check. The marker auto-flips to an Unexpected Pass (error) once
the reports are resolved, prompting removal of the gate.

Resolution
  1. Fix the in-place Euler interpolant (euler.jl:199) — a real bug.
  2. Initialize q11 / cur_t unconditionally (or restructure to a single
    if/else) so JET 0.11 can prove the binding, then drop the jet_broken gate.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the Julia 1.12 report with JET.test_package in test/qa, then inspect test/qa/qa.jl and the cited interpolant and solver files. Address the undefined Euler path and the q11/cur_t findings across the listed files, rerun the QA checks on Julia 1.10–1.12, and confirm the jet_broken gate can be removed.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
backend, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.