Skip to content

Commit eb2cfbd

Browse files
committed
Make OverflowError more informative
1 parent 9363b49 commit eb2cfbd

16 files changed

+47
-25
lines changed

NEWS.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,12 @@ Deprecated or removed
242242
* `fieldnames` now operates only on types. To get the names of fields in an object, use
243243
`fieldnames(typeof(x))` ([#22350]).
244244

245-
* `InexactError` and `DomainError` now take
245+
* `InexactError`, `DomainError`, and `OverflowError` now take
246246
arguments. `InexactError(func::Symbol, type, -3)` now prints as
247-
`ERROR: InexactError: func(type, -3)`, and `DomainError(val,
248-
[msg])` prints as `ERROR: DomainError with val:\nmsg`. ([#20005],
249-
[#22751])
247+
"ERROR: InexactError: func(type, -3)", `DomainError(val,
248+
[msg])` prints as "ERROR: DomainError with val:\nmsg",
249+
and `OverflowError(msg)` prints as "ERROR: OverflowError: msg".
250+
([#20005], [#22751], [#22761])
250251

251252
* The operating system identification functions: `is_linux`, `is_bsd`, `is_apple`, `is_unix`,
252253
and `is_windows`, have been deprecated in favor of `Sys.islinux`, `Sys.isbsd`, `Sys.isapple`,
@@ -1118,6 +1119,7 @@ Command-line option changes
11181119
[#22723]: https://github.com/JuliaLang/julia/issues/22723
11191120
[#22732]: https://github.com/JuliaLang/julia/issues/22732
11201121
[#22751]: https://github.com/JuliaLang/julia/issues/22751
1122+
[#22761]: https://github.com/JuliaLang/julia/issues/22761
11211123
[#22762]: https://github.com/JuliaLang/julia/issues/22762
11221124
[#22793]: https://github.com/JuliaLang/julia/issues/22793
11231125
[#22796]: https://github.com/JuliaLang/julia/issues/22796

base/boot.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ struct BoundsError <: Exception
212212
BoundsError(@nospecialize(a), i) = (@_noinline_meta; new(a,i))
213213
end
214214
struct DivideError <: Exception end
215-
struct OverflowError <: Exception end
215+
struct COverflowError <: Exception end
216216
struct OutOfMemoryError <: Exception end
217217
struct ReadOnlyMemoryError<: Exception end
218218
struct SegmentationFault <: Exception end
@@ -241,6 +241,9 @@ struct InexactError <: Exception
241241

242242
InexactError(f::Symbol, @nospecialize(T), @nospecialize(val)) = (@_noinline_meta; new(f, T, val))
243243
end
244+
struct OverflowError <: Exception
245+
msg
246+
end
244247

245248
abstract type DirectIndexString <: AbstractString end
246249

base/checked.jl

+12-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Core.Intrinsics:
1313
checked_srem_int,
1414
checked_uadd_int, checked_usub_int, checked_umul_int, checked_udiv_int,
1515
checked_urem_int
16-
import Base: no_op_err, @_inline_meta
16+
import Base: no_op_err, @_inline_meta, @_noinline_meta
1717

1818
# define promotion behavior for checked operations
1919
checked_add(x::Integer, y::Integer) = checked_add(promote(x,y)...)
@@ -90,16 +90,18 @@ The overflow protection may impose a perceptible performance penalty.
9090
function checked_neg(x::T) where T<:Integer
9191
checked_sub(T(0), x)
9292
end
93+
throw_overflowerr_negation(x) = (@_noinline_meta;
94+
throw(OverflowError("checked arithmetic: cannot compute -x for x = $x::$(typeof(x))")))
9395
if BrokenSignedInt != Union{}
9496
function checked_neg(x::BrokenSignedInt)
9597
r = -x
96-
(x<0) & (r<0) && throw(OverflowError())
98+
(x<0) & (r<0) && throw_overflowerr_negation(x)
9799
r
98100
end
99101
end
100102
if BrokenUnsignedInt != Union{}
101103
function checked_neg(x::T) where T<:BrokenUnsignedInt
102-
x != 0 && throw(OverflowError())
104+
x != 0 && throw_overflowerr_negation(x)
103105
T(0)
104106
end
105107
end
@@ -117,7 +119,7 @@ function checked_abs end
117119

118120
function checked_abs(x::SignedInt)
119121
r = ifelse(x<0, -x, x)
120-
r<0 && throw(OverflowError())
122+
r<0 && throw(OverflowError(string("checked arithmetic: cannot compute |x| for x = ", x, "::", typeof(x))))
121123
r
122124
end
123125
checked_abs(x::UnsignedInt) = x
@@ -152,6 +154,9 @@ end
152154
end
153155

154156

157+
throw_overflowerr_binaryop(op, x, y) = (@_noinline_meta;
158+
throw(OverflowError("$x $op $y overflowed for type $(typeof(x))")))
159+
155160
"""
156161
Base.checked_add(x, y)
157162
@@ -162,7 +167,7 @@ The overflow protection may impose a perceptible performance penalty.
162167
function checked_add(x::T, y::T) where T<:Integer
163168
@_inline_meta
164169
z, b = add_with_overflow(x, y)
165-
b && throw(OverflowError())
170+
b && throw_overflowerr_binaryop(:+, x, y)
166171
z
167172
end
168173

@@ -219,7 +224,7 @@ The overflow protection may impose a perceptible performance penalty.
219224
function checked_sub(x::T, y::T) where T<:Integer
220225
@_inline_meta
221226
z, b = sub_with_overflow(x, y)
222-
b && throw(OverflowError())
227+
b && throw_overflowerr_binaryop(:-, x, y)
223228
z
224229
end
225230

@@ -284,7 +289,7 @@ The overflow protection may impose a perceptible performance penalty.
284289
function checked_mul(x::T, y::T) where T<:Integer
285290
@_inline_meta
286291
z, b = mul_with_overflow(x, y)
287-
b && throw(OverflowError())
292+
b && throw_overflowerr_binaryop(:*, x, y)
288293
z
289294
end
290295

base/combinatorics.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ end
1616

1717
function factorial_lookup(n::Integer, table, lim)
1818
n < 0 && throw(DomainError(n, "`n` must not be negative."))
19-
n > lim && throw(OverflowError())
19+
n > lim && throw(OverflowError(string(n, " is too large to look up in the table")))
2020
n == 0 && return one(n)
2121
@inbounds f = table[n]
2222
return oftype(n, f)

base/deprecated.jl

+6
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,12 @@ function DomainError()
15491549
DomainError(nothing)
15501550
end
15511551

1552+
# PR #22761
1553+
function OverflowError()
1554+
depwarn("OverflowError now supports a message string, use `OverflowError(msg)` instead.", :OverflowError)
1555+
OverflowError("")
1556+
end
1557+
15521558
# PR #22703
15531559
@deprecate Bidiagonal(dv::AbstractVector, ev::AbstractVector, isupper::Bool) Bidiagonal(dv, ev, ifelse(isupper, :U, :L))
15541560
@deprecate Bidiagonal(dv::AbstractVector, ev::AbstractVector, uplo::Char) Bidiagonal(dv, ev, ifelse(uplo == 'U', :U, :L))

base/docs/helpdb/Base.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,7 @@ used only with extreme caution, as it can cause memory use to grow without bound
15091509
gc_enable
15101510

15111511
"""
1512-
OverflowError()
1512+
OverflowError(msg)
15131513
15141514
The result of an expression is too large for the specified type and will cause a wraparound.
15151515
"""

base/gmp.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ isqrt(x::BigInt) = MPZ.sqrt(x)
494494

495495
function bigint_pow(x::BigInt, y::Integer)
496496
if y<0; throw(DomainError(y, "`y` cannot be negative.")); end
497+
@noinline throw1(y) =
498+
throw(OverflowError("exponent $y is too large and computation will overflow"))
497499
if x== 1; return x; end
498500
if x==-1; return isodd(y) ? x : -x; end
499501
if y>typemax(Culong)
@@ -507,7 +509,7 @@ function bigint_pow(x::BigInt, y::Integer)
507509
#
508510
#Assume that the answer will definitely overflow.
509511

510-
throw(OverflowError())
512+
throw1(y)
511513
end
512514
return x^convert(Culong, y)
513515
end

base/intfuncs.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ end
2828
# binary GCD (aka Stein's) algorithm
2929
# about 1.7x (2.1x) faster for random Int64s (Int128s)
3030
function gcd(a::T, b::T) where T<:Union{Int64,UInt64,Int128,UInt128}
31+
@noinline throw1(a, b) = throw(OverflowError("gcd($a, $b) overflows"))
3132
a == 0 && return abs(b)
3233
b == 0 && return abs(a)
3334
za = trailing_zeros(a)
@@ -44,7 +45,7 @@ function gcd(a::T, b::T) where T<:Union{Int64,UInt64,Int128,UInt128}
4445
end
4546
r = u << k
4647
# T(r) would throw InexactError; we want OverflowError instead
47-
r > typemax(T) && throw(OverflowError())
48+
r > typemax(T) && throw1(a, b)
4849
r % T
4950
end
5051

@@ -841,6 +842,7 @@ julia> factorial(5) ÷ (factorial(5-3) * factorial(3))
841842
```
842843
"""
843844
function binomial(n::T, k::T) where T<:Integer
845+
n0, k0 = n, k
844846
k < 0 && return zero(T)
845847
sgn = one(T)
846848
if n < 0
@@ -861,7 +863,7 @@ function binomial(n::T, k::T) where T<:Integer
861863
while rr <= k
862864
xt = div(widemul(x, nn), rr)
863865
x = xt
864-
x == xt || throw(OverflowError())
866+
x == xt || throw(OverflowError("binomial($n0, $k0) overflows"))
865867
rr += 1
866868
nn += 1
867869
end

base/parse.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::
112112
n, ov_mul = mul_with_overflow(n, base)
113113
n, ov_add = add_with_overflow(n, d)
114114
if ov_mul | ov_add
115-
raise && throw(OverflowError())
115+
raise && throw(OverflowError("overflow parsing $(repr(SubString(s,startpos,endpos)))"))
116116
return _n
117117
end
118118
(i > endpos) && return Nullable{T}(n)

base/rational.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,11 @@ isinteger(x::Rational) = x.den == 1
233233

234234
-(x::Rational) = (-x.num) // x.den
235235
function -(x::Rational{T}) where T<:Signed
236-
x.num == typemin(T) && throw(OverflowError())
236+
x.num == typemin(T) && throw(OverflowError("rational numerator is typemin(T)"))
237237
(-x.num) // x.den
238238
end
239239
function -(x::Rational{T}) where T<:Unsigned
240-
x.num != zero(T) && throw(OverflowError())
240+
x.num != zero(T) && throw(OverflowError("cannot negate unsigned number"))
241241
x
242242
end
243243

base/replutil.jl

+2
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ function showerror(io::IO, ex::SystemError)
261261
end
262262
end
263263
showerror(io::IO, ::DivideError) = print(io, "DivideError: integer division error")
264+
showerror(io::IO, ::Core.COverflowError) = print(io, "COverflowError:")
264265
showerror(io::IO, ::StackOverflowError) = print(io, "StackOverflowError:")
265266
showerror(io::IO, ::UndefRefError) = print(io, "UndefRefError: access to undefined reference")
266267
showerror(io::IO, ::EOFError) = print(io, "EOFError: read end of file")
@@ -275,6 +276,7 @@ showerror(io::IO, ex::KeyError) = print(io, "KeyError: key $(repr(ex.key)) not f
275276
showerror(io::IO, ex::InterruptException) = print(io, "InterruptException:")
276277
showerror(io::IO, ex::ArgumentError) = print(io, "ArgumentError: $(ex.msg)")
277278
showerror(io::IO, ex::AssertionError) = print(io, "AssertionError: $(ex.msg)")
279+
showerror(io::IO, ex::OverflowError) = print(io, "OverflowError: $(ex.msg)")
278280

279281
function showerror(io::IO, ex::UndefVarError)
280282
if ex.var in [:UTF16String, :UTF32String, :WString, :utf16, :utf32, :wstring, :RepString]

src/codegen.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -6015,7 +6015,7 @@ static void init_julia_llvm_env(Module *m)
60156015
global_jlvalue_to_llvm("jl_emptytuple", &jl_emptytuple, m);
60166016
global_jlvalue_to_llvm("jl_diverror_exception", &jl_diverror_exception, m);
60176017
global_jlvalue_to_llvm("jl_undefref_exception", &jl_undefref_exception, m);
6018-
global_jlvalue_to_llvm("jl_overflow_exception", &jl_overflow_exception, m);
6018+
global_jlvalue_to_llvm("jl_c_overflow_exception", &jl_c_overflow_exception, m);
60196019

60206020
jlRTLD_DEFAULT_var =
60216021
new GlobalVariable(*m, T_pint8,

src/datatype.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
347347
return;
348348
throw_ovf:
349349
if (descsz >= jl_page_size) free(desc);
350-
jl_throw(jl_overflow_exception);
350+
jl_throw(jl_c_overflow_exception);
351351
}
352352

353353
extern int jl_boot_file_loaded;

src/init.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ void jl_get_builtin_hooks(void)
785785
jl_errorexception_type = (jl_datatype_t*)core("ErrorException");
786786
jl_stackovf_exception = jl_new_struct_uninit((jl_datatype_t*)core("StackOverflowError"));
787787
jl_diverror_exception = jl_new_struct_uninit((jl_datatype_t*)core("DivideError"));
788-
jl_overflow_exception = jl_new_struct_uninit((jl_datatype_t*)core("OverflowError"));
788+
jl_c_overflow_exception = jl_new_struct_uninit((jl_datatype_t*)core("COverflowError"));
789789
jl_undefref_exception = jl_new_struct_uninit((jl_datatype_t*)core("UndefRefError"));
790790
jl_undefvarerror_type = (jl_datatype_t*)core("UndefVarError");
791791
jl_interrupt_exception = jl_new_struct_uninit((jl_datatype_t*)core("InterruptException"));

src/jltypes.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ jl_value_t *jl_segv_exception;
120120
#endif
121121
JL_DLLEXPORT jl_value_t *jl_diverror_exception;
122122
JL_DLLEXPORT jl_value_t *jl_domain_exception;
123-
JL_DLLEXPORT jl_value_t *jl_overflow_exception;
123+
JL_DLLEXPORT jl_value_t *jl_c_overflow_exception;
124124
JL_DLLEXPORT jl_value_t *jl_undefref_exception;
125125
jl_value_t *jl_interrupt_exception;
126126
jl_datatype_t *jl_boundserror_type;

src/julia.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ extern JL_DLLEXPORT jl_value_t *jl_stackovf_exception;
529529
extern JL_DLLEXPORT jl_value_t *jl_memory_exception;
530530
extern JL_DLLEXPORT jl_value_t *jl_readonlymemory_exception;
531531
extern JL_DLLEXPORT jl_value_t *jl_diverror_exception;
532-
extern JL_DLLEXPORT jl_value_t *jl_overflow_exception;
532+
extern JL_DLLEXPORT jl_value_t *jl_c_overflow_exception;
533533
extern JL_DLLEXPORT jl_value_t *jl_undefref_exception;
534534
extern JL_DLLEXPORT jl_value_t *jl_interrupt_exception;
535535
extern JL_DLLEXPORT jl_datatype_t *jl_boundserror_type;

0 commit comments

Comments
 (0)