Formatting.jl icon indicating copy to clipboard operation
Formatting.jl copied to clipboard

Formatting fails for `typemin(T<:Integer)`

Open jagot opened this issue 3 years ago • 2 comments

Consider

f = FormatExpr("{1:+d}")
for T in (Int8,Int16,Int32,Int64)
    @test format(f, typemin(T)) == string(typemin(T)) # Crashes
    @test format(f, typemax(T)) == "+"*string(typemax(T)) # Works
end

The first test (for typemin) crashes with the error

Error During Test at REPL[26]:2
  Test threw exception
  Expression: format(f, typemin(T)) == string(typemin(T))
  InexactError: check_top_bit(UInt32, -80)
  Stacktrace:
    [1] throw_inexacterror(f::Symbol, #unused#::Type{UInt32}, val::Int32)
      @ Core ./boot.jl:614
    [2] check_top_bit
      @ ./boot.jl:628 [inlined]
    [3] toUInt32
      @ ./boot.jl:727 [inlined]
    [4] UInt32
      @ ./boot.jl:768 [inlined]
    [5] +
      @ ./char.jl:242 [inlined]
    [6] _digitchar
      @ ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:63 [inlined]
    [7] _pfmt_intdigits(out::IOBuffer, ax::Int8, op::Formatting._Dec)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:102
    [8] _pfmt_int(out::IOBuffer, sch::Char, ip::String, zs::Int64, ax::Int8, op::Formatting._Dec)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:89
    [9] _pfmt_i(out::IOBuffer, fs::FormatSpec, x::Int8, op::Formatting._Dec)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtcore.jl:126
   [10] printfmt(io::IOBuffer, fs::FormatSpec, x::Int8)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/fmtspec.jl:182
   [11] printfmt(io::IOBuffer, fe::FormatExpr, args::Int8)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/formatexpr.jl:147
   [12] sprint(::Function, ::FormatExpr, ::Vararg{Any}; context::Nothing, sizehint::Int64)
      @ Base ./strings/io.jl:114
   [13] sprint
      @ ./strings/io.jl:107 [inlined]
   [14] format(fe::FormatExpr, args::Int8)
      @ Formatting ~/.julia/packages/Formatting/BwWBf/src/formatexpr.jl:165

jagot avatar Mar 28 '23 13:03 jagot

Digging a bit, it fails because we cannot compute the absolute value of typemin(i::Integer), since in two-complement binary representation, the absolute value of the minimum number is one larger than the maximum number:

julia> abs(typemin(Int8))
-128

This makes the following logic break: https://github.com/JuliaIO/Formatting.jl/blob/e4c9f60020e965a72abae049ddac7e02bf986067/src/fmtcore.jl#L107-L139

jagot avatar Mar 28 '23 14:03 jagot

Note that this is not broken if you use Format instead of Formatting

ScottPJones avatar Jan 30 '24 15:01 ScottPJones