Skip to content

Make the package JET-clean and run JET on all reported code - #363

Open
PatrickHaecker wants to merge 3 commits into
JuliaMath:masterfrom
PatrickHaecker:jet-clean
Open

PatrickHaecker wants to merge 3 commits into
JuliaMath:masterfrom
PatrickHaecker:jet-clean

Conversation

@PatrickHaecker

@PatrickHaecker PatrickHaecker commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

I think I found a solution which is the best of both worlds from our discussion of the feature.

The JET workflow analyzed only FixedPointNumbers itself and printed an unrestricted report on the side, which is less efficient can be confusing as they differed. Reports from Base code reached through FixedPointNumbers are worth catching as well, so the workflow now runs test_package without target_modules and fails on any report. This helps to find regressions both in future FixedPointNumbers versions and in future Julia versions.

This required removing the three remaining causes of reports on Julia 1.10 and 1.13 when not limiting JET to FixedPointNumbers:

  • signed and unsigned for FixedPoint threw a MethodError only because rem has no method for a type argument. They now throw the MethodError explicitly. This enables JET to understand that this is on purpose (and humans who haven't read the comment).
  • isinteger reached the Fixed method of _floor through the generic _trunc for FixedPoint{<:Unsigned}, with an impossible Fixed{Union{}}, because Union{} is both Signed and Unsigned. Bounding that method by T <: Signed limits the overlap to Fixed{Union{}, f}, which has no values and now has its own method. _trunc stays unchanged.
  • rand! converted the array pointer with reinterpret, whose Base internals JET reports on Julia 1.10. The Ptr{T} constructor does the same conversion and is better style anyway.

This seems to combine the best of both worlds
[from the discussion](JuliaMath#358 (comment))
of the feature.

The JET workflow analyzed only FixedPointNumbers itself and printed an
unrestricted report on the side, which can be confusing. Reports from Base
code reached through FixedPointNumbers are worth catching as well, so
the workflow now runs `test_package` without `target_modules` and fails
on any report. This helps to find regressions both in future FPN and in
future Julia versions.

This required removing three causes of reports on Julia 1.10 and 1.13:

- `signed` and `unsigned` for `FixedPoint` threw a `MethodError` only
  because `rem` has no method for a type argument. They now throw the
  `MethodError` explicitly.
- `_trunc` for `FixedPoint{<:Unsigned}` also dispatched to the `Fixed`
  method of `_floor`, with an impossible `Fixed{Union{}}`. It is now
  defined for `Normed`, the only unsigned `FixedPoint` type.
- `rand!` converted the array pointer with `reinterpret`, whose Base
  internals JET reports on Julia 1.10. The `Ptr{T}` constructor does
  the same conversion and is better style anyway.
@codecov

codecov Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.78%. Comparing base (d62abf3) to head (6a7e78f).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #363      +/-   ##
==========================================
+ Coverage   96.75%   96.78%   +0.03%     
==========================================
  Files           7        7              
  Lines         800      808       +8     
==========================================
+ Hits          774      782       +8     
  Misses         26       26              

☔ 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.

@kimikage kimikage added the breaking Major breaking change label Oct 17, 2026

@kimikage kimikage left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach for the _trunc case is not appropriate.
If we make an exception for this particular case, it could lead to “incorrect” solutions for other potential issues involving non-concrete types.

If we were to address the JET report, it would be within throw_converterror.

I'll avoid getting into a debate about whether this truly qualifies as a breaking change, but I've labeled it "breaking" with the intention that it should be addressed in FPN v0.10.0.

Comment thread .github/workflows/JET.yml
Comment thread src/FixedPointNumbers.jl Outdated
Comment thread src/FixedPointNumbers.jl
Comment thread src/FixedPointNumbers.jl
The generic `_trunc` for `FixedPoint{<:Unsigned}` stays available to unsigned
`FixedPoint` types outside this package. JET reached the `Fixed` method of
`_floor` through it, because `Union{}` is both `Signed` and `Unsigned`. Bounding
that method by `T <: Signed` limits the overlap to `Fixed{Union{}, f}`, which
has no values and now has its own method.

The comment on `signed` and `unsigned` now only states why the methods exist.
@PatrickHaecker

Copy link
Copy Markdown
Collaborator Author

Thanks for the review, @kimikage. I think I have covered everything. Please check again.

@kimikage

Copy link
Copy Markdown
Collaborator

I haven’t tested it myself, but I suspect there are other pieces of code that break in the T == Union{} case.
Are you planning to add guards to all of them?
And are you planning to add test cases to all of them just to cover those lines?
In terms of the goal of eliminating JET warnings, this clearly constitutes an anti-pattern.
Such guards are only justified when ambiguity or invalidation actually causes real harm.

@kimikage kimikage removed the breaking Major breaking change label Oct 18, 2026
`Union{}` is a subtype of every type, so methods for `Type{X} where {X <: FixedPoint}`
also match it. Calls like `floattype(Union{})` or `0.5 % Union{}` therefore ended in
ambiguity errors that named internal functions, or in errors from inside unrelated
methods. Since Julia 1.10, a method of the form `f(..., ::Type{Union{}}, slurp...)`
takes precedence over all other methods of `f`, which is how Base handles the same
case.

The exported functions with a type argument get such a method. `*`, `rem` and the
functions of `Base.Checked` belong to Base, so the internal `_convert` and `_rem`
they call are guarded instead. On older Julia versions, these calls still throw an
ambiguous `MethodError`.

The `Fixed{Union{}}` method of `_floor` cannot be reached at runtime, because
`Fixed{Union{}}` has no values, so it is excluded from coverage.
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.

2 participants