• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / 1285

25 Sep 2025 09:41PM UTC coverage: 70.929% (-6.0%) from 76.923%
1285

push

buildkite

web-flow
Fix gcdx and lcm with mixed signed/unsigned arguments (#59628)

Add `gcdx(a::Signed, b::Unsigned)` and `gcdx(a::Unsigned, b::Signed)`
methods to fix #58025:
```julia
julia> gcdx(UInt16(100), Int8(-101))  # pr
(0x0001, 0xffff, 0xffff)

julia> gcdx(UInt16(100), Int8(-101))  # master, incorrect result
(0x0005, 0xf855, 0x0003)
```

Also add the equivalent methods for `lcm` to fix the systematic
`InexactError` when one argument is a negative `Signed` and the other is
any `Unsigned`:
```julia
julia> lcm(UInt16(100), Int8(-101))  # pr
0x2774

julia> lcm(UInt16(100), Int8(-101))  # master, error
ERROR: InexactError: trunc(UInt16, -101)
Stacktrace:
 [1] throw_inexacterror(func::Symbol, to::Type, val::Int8)
   @ Core ./boot.jl:866
 [2] check_sign_bit
   @ ./boot.jl:872 [inlined]
 [3] toUInt16
   @ ./boot.jl:958 [inlined]
 [4] UInt16
   @ ./boot.jl:1011 [inlined]
 [5] convert
   @ ./number.jl:7 [inlined]
 [6] _promote
   @ ./promotion.jl:379 [inlined]
 [7] promote
   @ ./promotion.jl:404 [inlined]
 [8] lcm(a::UInt16, b::Int8)
   @ Base ./intfuncs.jl:152
 [9] top-level scope
   @ REPL[62]:1
```

Inspired by
https://github.com/JuliaLang/julia/pull/59487#issuecomment-3258209203.
The difference is that the solution proposed in this PR keeps the
current correct result type for inputs such as `(::Int16, ::UInt8)`.

10 of 10 new or added lines in 1 file covered. (100.0%)

4780 existing lines in 122 files now uncovered.

50633 of 71385 relevant lines covered (70.93%)

7422080.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.49
/Compiler/src/reflection_interface.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
_findall_matches(interp::AbstractInterpreter, @nospecialize(tt)) = findall(tt, method_table(interp))
6,016✔
4
_default_interp(world::UInt) = NativeInterpreter(world)
263✔
5

6
_may_throw_methoderror(matches::MethodLookupResult) =
1,845✔
7
    matches.ambig || !any(match::Core.MethodMatch->match.fully_covers, matches.matches)
923✔
8

9
function _infer_exception_type(interp::AbstractInterpreter, @nospecialize(tt), optimize::Bool)
98✔
10
    matches = _findall_matches(interp, tt)
98✔
11
    matches === nothing && return nothing
98✔
12
    exct = Union{}
98✔
13
    if _may_throw_methoderror(matches)
196✔
14
        # account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
UNCOV
15
        exct = MethodError
×
16
    end
17
    for match in matches.matches
98✔
18
        match = match::Core.MethodMatch
98✔
19
        frame = typeinf_frame(interp, match, #=run_optimizer=#optimize)
98✔
20
        frame === nothing && return Any
98✔
21
        exct = tmerge(exct, widenconst(frame.result.exc_result))
98✔
22
    end
98✔
23
    return exct
98✔
24
end
25

26
function _infer_effects(interp::AbstractInterpreter, @nospecialize(tt), optimize::Bool)
825✔
27
    matches = _findall_matches(interp, tt)
825✔
28
    matches === nothing && return nothing
825✔
29
    effects = EFFECTS_TOTAL
825✔
30
    if _may_throw_methoderror(matches)
1,649✔
31
        # account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
32
        effects = Effects(effects; nothrow=false)
2✔
33
    end
34
    for match in matches.matches
825✔
35
        match = match::Core.MethodMatch
826✔
36
        frame = typeinf_frame(interp, match, #=run_optimizer=#optimize)
826✔
37
        frame === nothing && return Effects()
826✔
38
        effects = merge_effects(effects, frame.result.ipo_effects)
1,652✔
39
    end
826✔
40
    return effects
825✔
41
end
42

UNCOV
43
function statement_costs!(interp::AbstractInterpreter, cost::Vector{Int}, body::Vector{Any}, src::Union{CodeInfo, IRCode}, match::Core.MethodMatch)
×
UNCOV
44
    params = OptimizationParams(interp)
×
UNCOV
45
    sptypes = VarState[VarState(sp, false) for sp in match.sparams]
×
UNCOV
46
    return statement_costs!(cost, body, src, sptypes, params)
×
47
end
48

49
function findsup_mt(@nospecialize(tt), world, method_table)
588✔
50
    if method_table === nothing
588✔
51
        table = InternalMethodTable(world)
588✔
52
    elseif method_table isa Core.MethodTable
×
53
        table = OverlayMethodTable(world, method_table)
×
54
    else
55
        table = method_table
×
56
    end
57
    return findsup(tt, table)
588✔
58
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc