Skip to content

Commit 0e1551a

Browse files
Improve static analysis: fix JET errors and add JET tests (#117)
This PR addresses type instabilities detected by JET.jl analysis: **JET issues fixed:** 1. `math.jl`: Fixed `find_amsa` function returning `false` instead of a proper type - Changed fallback to return `nothing` instead of propagating non-AMSA values - Added type assertion in `copy` to inform the compiler that AMSAStyle guarantees an AMSA exists - Added explicit method `find_amsa(x::AMSA) = x` for direct dispatch - Added `find_amsa(::Nothing, rest)` to handle the nothing case properly 2. `print_human_readable.jl`: Fixed potential `nothing` indexing errors - `findfirst` and `findnext` can return `nothing` when pattern not found - Added proper nil-checks before indexing into results **New tests added:** - Added `test/jet_tests.jl` with JET.jl static analysis test - Added JET as a test dependency in Project.toml All existing tests pass with these changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Code <noreply@anthropic.com>
1 parent 8f3482f commit 0e1551a

5 files changed

Lines changed: 28 additions & 6 deletions

File tree

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ DiffEqBase = "6.5"
3030
DifferentiationInterface = "0.7.7"
3131
FiniteDiff = "2.3"
3232
ForwardDiff = "0.10, 1.3"
33+
JET = "0.9, 0.10, 0.11"
3334
OrdinaryDiffEq = "6"
3435
OrdinaryDiffEqCore = "1.30.0, 2.0"
3536
OrdinaryDiffEqDifferentiation = "1.16"
@@ -42,9 +43,10 @@ StochasticDiffEq = "6.13"
4243
julia = "1.10"
4344

4445
[extras]
46+
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
4547
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
4648
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
4749
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
4850

4951
[targets]
50-
test = ["OrdinaryDiffEq", "SafeTestsets", "Test"]
52+
test = ["JET", "OrdinaryDiffEq", "SafeTestsets", "Test"]

src/math.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ end
1515
Broadcast.BroadcastStyle(::Type{<:AMSA}) = AMSAStyle()
1616

1717
@inline function Base.copy(bc::Broadcast.Broadcasted{<:AMSAStyle})
18-
first_amsa = find_amsa(bc)
18+
first_amsa = find_amsa(bc)::AMSA # Type assertion: AMSAStyle guarantees an AMSA exists
1919

2020
out = similar(first_amsa, Base.Broadcast._broadcast_getindex_eltype(bc))
2121

@@ -71,12 +71,16 @@ _nnodes(args::Tuple{}) = 0
7171

7272
"""
7373
`A = find_amsa(As)` returns the first AMSA among the arguments.
74+
75+
Returns the first `AbstractMultiScaleArray` found in the arguments, or `nothing` if none found.
7476
"""
7577
find_amsa(bc::Base.Broadcast.Broadcasted) = find_amsa(bc.args)
76-
find_amsa(args::Tuple) = !isempty(args) && find_amsa(find_amsa(args[1]), Base.tail(args))
77-
find_amsa(x) = x
78+
find_amsa(args::Tuple) = isempty(args) ? nothing : find_amsa(find_amsa(args[1]), Base.tail(args))
79+
find_amsa(x) = nothing
80+
find_amsa(x::AMSA) = x
7881
find_amsa(a::AMSA, rest) = a
7982
find_amsa(::Any, rest) = find_amsa(rest)
83+
find_amsa(::Nothing, rest) = find_amsa(rest)
8084

8185
any_non_amsa(bc::Base.Broadcast.Broadcasted) = any_non_amsa(bc.args)
8286
any_non_amsa(args::Tuple) = any_non_amsa(any_non_amsa(args[1]), Base.tail(args))

src/print_human_readable.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,12 @@ function print_human_readable(X::AbstractMultiScaleArray; n_char_per_name = 6,
118118
# ^^^^^^^^^^^
119119
for level in length(toprint):-1:1
120120
while occursin("+ ", toprint[level])
121-
Move = findfirst("+ ", toprint[level])[1]
122-
To = findnext(" |", toprint[level], Move[end])[1]
121+
move_range = findfirst("+ ", toprint[level])
122+
move_range === nothing && break
123+
Move = first(move_range)
124+
to_range = findnext(" |", toprint[level], last(move_range))
125+
to_range === nothing && break
126+
To = first(to_range)
123127
toprint[level] = join([
124128
toprint[level][1:(Move - 1)],
125129
toprint[level][(Move + 1):To],

test/jet_tests.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using JET
2+
using MultiScaleArrays
3+
4+
@testset "JET static analysis" begin
5+
# Run JET analysis on the package
6+
report = JET.report_package(MultiScaleArrays;
7+
target_modules = (MultiScaleArrays,))
8+
@test length(JET.get_reports(report)) == 0
9+
end

test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using MultiScaleArrays, OrdinaryDiffEq, DiffEqBase, StochasticDiffEq, SafeTestsets
22
using Test
33

4+
@time @testset "JET Static Analysis" begin
5+
include("jet_tests.jl")
6+
end
47
@time @testset "Tuple Nodes" begin
58
include("tuple_nodes.jl")
69
end

0 commit comments

Comments
 (0)