diff --git a/base/boot.jl b/base/boot.jl index 5ba20e39a67041..f3109e468463a7 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -206,7 +206,7 @@ struct BoundsError <: Exception end struct DivideError <: Exception end struct DomainError <: Exception end -struct OverflowError <: Exception end +struct FieldOverflowError <: Exception end struct OutOfMemoryError <: Exception end struct ReadOnlyMemoryError<: Exception end struct SegmentationFault <: Exception end @@ -229,6 +229,9 @@ struct InexactError <: Exception InexactError(f::Symbol, T::ANY, val::ANY) = (@_noinline_meta; new(f, T, val)) end +struct OverflowError <: Exception + args +end abstract type DirectIndexString <: AbstractString end diff --git a/base/checked.jl b/base/checked.jl index 215f12a62b52ea..58125652d5869c 100644 --- a/base/checked.jl +++ b/base/checked.jl @@ -13,7 +13,7 @@ import Core.Intrinsics: checked_srem_int, checked_uadd_int, checked_usub_int, checked_umul_int, checked_udiv_int, checked_urem_int -import Base: no_op_err, @_inline_meta +import Base: no_op_err, @_inline_meta, @_noinline_meta # define promotion behavior for checked operations checked_add(x::Integer, y::Integer) = checked_add(promote(x,y)...) @@ -90,16 +90,18 @@ The overflow protection may impose a perceptible performance penalty. function checked_neg(x::T) where T<:Integer checked_sub(T(0), x) end +throw_overflowerr_negation(x) = (@_noinline_meta; + throw(OverflowError("cannot compute -x for x = $x::$(typeof(x))"))) if BrokenSignedInt != Union{} function checked_neg(x::BrokenSignedInt) r = -x - (x<0) & (r<0) && throw(OverflowError()) + (x<0) & (r<0) && throw_overflowerr_negation(x) r end end if BrokenUnsignedInt != Union{} function checked_neg(x::T) where T<:BrokenUnsignedInt - x != 0 && throw(OverflowError()) + x != 0 && throw_overflowerr_negation(x) T(0) end end @@ -117,7 +119,7 @@ function checked_abs end function checked_abs(x::SignedInt) r = ifelse(x<0, -x, x) - r<0 && throw(OverflowError()) + r<0 && throw(OverflowError(string("cannot compute |x| for x = ", x, "::", typeof(x)))) r end checked_abs(x::UnsignedInt) = x @@ -152,6 +154,9 @@ end end +throw_overflowerr_binaryop(op, x, y, T) = (@_noinline_meta; + throw(OverflowError("$x $op $y overflowed for type $T"))) + """ Base.checked_add(x, y) @@ -162,7 +167,7 @@ The overflow protection may impose a perceptible performance penalty. function checked_add(x::T, y::T) where T<:Integer @_inline_meta z, b = add_with_overflow(x, y) - b && throw(OverflowError()) + b && throw_overflowerr_binaryop(:+, x, y, T) z end @@ -219,7 +224,7 @@ The overflow protection may impose a perceptible performance penalty. function checked_sub(x::T, y::T) where T<:Integer @_inline_meta z, b = sub_with_overflow(x, y) - b && throw(OverflowError()) + b && throw_overflowerr_binaryop(:-, x, y, T) z end @@ -284,7 +289,7 @@ The overflow protection may impose a perceptible performance penalty. function checked_mul(x::T, y::T) where T<:Integer @_inline_meta z, b = mul_with_overflow(x, y) - b && throw(OverflowError()) + b && throw_overflowerr_binaryop(:*, x, y, T) z end diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 137fb439c6ec64..d5d0edf6114c9d 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -16,7 +16,7 @@ end function factorial_lookup(n::Integer, table, lim) n < 0 && throw(DomainError()) - n > lim && throw(OverflowError()) + n > lim && throw(OverflowError(string(n, " is too large to look up in the table"))) n == 0 && return one(n) @inbounds f = table[n] return oftype(n, f) diff --git a/base/deprecated.jl b/base/deprecated.jl index 33d9d780f16a2b..226d66eae7dd56 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1561,6 +1561,12 @@ function InexactError() InexactError(:none, Any, nothing) end +# PR #?? +function OverflowError() + depwarn("OverflowError now supports a message string, use `OverflowError(msg)` instead.", :OverflowError) + OverflowError("") +end + # PR #22703 @deprecate Bidiagonal(dv::AbstractVector, ev::AbstractVector, isupper::Bool) Bidiagonal(dv, ev, ifelse(isupper, :U, :L)) @deprecate Bidiagonal(dv::AbstractVector, ev::AbstractVector, uplo::Char) Bidiagonal(dv, ev, ifelse(uplo == 'U', :U, :L)) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 3297d1e1d1b049..13a8f2f7ecbc31 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1593,7 +1593,7 @@ used only with extreme caution, as it can cause memory use to grow without bound gc_enable """ - OverflowError() + OverflowError(msg) The result of an expression is too large for the specified type and will cause a wraparound. """ diff --git a/base/gmp.jl b/base/gmp.jl index af284cdc2ab2e2..a1b2aef5f43662 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -482,6 +482,8 @@ isqrt(x::BigInt) = MPZ.sqrt(x) ^(x::BigInt, y::Culong) = MPZ.pow_ui(x, y) function bigint_pow(x::BigInt, y::Integer) + @noinline throw1(y) = + throw(OverflowError("exponent $y is too large and computation will overflow")) if y<0; throw(DomainError()); end if x== 1; return x; end if x==-1; return isodd(y) ? x : -x; end @@ -496,7 +498,7 @@ function bigint_pow(x::BigInt, y::Integer) # #Assume that the answer will definitely overflow. - throw(OverflowError()) + throw1(y) end return x^convert(Culong, y) end diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 0d0c2af9d5ed0a..b6a4ecb6ef45ec 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -28,6 +28,7 @@ end # binary GCD (aka Stein's) algorithm # about 1.7x (2.1x) faster for random Int64s (Int128s) function gcd(a::T, b::T) where T<:Union{Int64,UInt64,Int128,UInt128} + @noinline throw1(a, b) = throw(OverflowError("gcd($a, $b) overflows")) a == 0 && return abs(b) b == 0 && return abs(a) za = trailing_zeros(a) @@ -44,7 +45,7 @@ function gcd(a::T, b::T) where T<:Union{Int64,UInt64,Int128,UInt128} end r = u << k # T(r) would throw InexactError; we want OverflowError instead - r > typemax(T) && throw(OverflowError()) + r > typemax(T) && throw1(a, b) r % T end @@ -824,6 +825,7 @@ julia> factorial(5) รท (factorial(5-3) * factorial(3)) ``` """ function binomial(n::T, k::T) where T<:Integer + n0, k0 = n, k k < 0 && return zero(T) sgn = one(T) if n < 0 @@ -844,7 +846,7 @@ function binomial(n::T, k::T) where T<:Integer while rr <= k xt = div(widemul(x, nn), rr) x = xt - x == xt || throw(OverflowError()) + x == xt || throw(OverflowError("binomial($n0, $k0) overflows")) rr += 1 nn += 1 end diff --git a/base/parse.jl b/base/parse.jl index 03d460d0585b8a..672b3d16f4fa69 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -112,7 +112,7 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: n, ov_mul = mul_with_overflow(n, base) n, ov_add = add_with_overflow(n, d) if ov_mul | ov_add - raise && throw(OverflowError()) + raise && throw(OverflowError("overflow parsing $(repr(SubString(s,startpos,endpos)))")) return _n end (i > endpos) && return Nullable{T}(n) diff --git a/base/rational.jl b/base/rational.jl index b6af61273dfcec..cc12ac946d44a3 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -233,11 +233,11 @@ isinteger(x::Rational) = x.den == 1 -(x::Rational) = (-x.num) // x.den function -(x::Rational{T}) where T<:Signed - x.num == typemin(T) && throw(OverflowError()) + x.num == typemin(T) && throw(OverflowError("rational numerator is typemin(T)")) (-x.num) // x.den end function -(x::Rational{T}) where T<:Unsigned - x.num != zero(T) && throw(OverflowError()) + x.num != zero(T) && throw(OverflowError("cannot negate unsigned number")) x end diff --git a/src/codegen.cpp b/src/codegen.cpp index a800306b9a7414..8844f86f7ed886 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6242,7 +6242,7 @@ static void init_julia_llvm_env(Module *m) global_jlvalue_to_llvm("jl_emptytuple", &jl_emptytuple, m); global_jlvalue_to_llvm("jl_diverror_exception", &jl_diverror_exception, m); global_jlvalue_to_llvm("jl_undefref_exception", &jl_undefref_exception, m); - global_jlvalue_to_llvm("jl_overflow_exception", &jl_overflow_exception, m); + global_jlvalue_to_llvm("jl_fieldoverflow_exception", &jl_fieldoverflow_exception, m); jlRTLD_DEFAULT_var = new GlobalVariable(*m, T_pint8, diff --git a/src/datatype.c b/src/datatype.c index e97a26ad53bf1a..a7b7e195382f77 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -347,7 +347,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) return; throw_ovf: if (descsz >= jl_page_size) free(desc); - jl_throw(jl_overflow_exception); + jl_throw(jl_fieldoverflow_exception); } extern int jl_boot_file_loaded; diff --git a/src/init.c b/src/init.c index 8d0974d8c5155a..308d01b7f423cd 100644 --- a/src/init.c +++ b/src/init.c @@ -785,7 +785,7 @@ void jl_get_builtin_hooks(void) jl_errorexception_type = (jl_datatype_t*)core("ErrorException"); jl_stackovf_exception = jl_new_struct_uninit((jl_datatype_t*)core("StackOverflowError")); jl_diverror_exception = jl_new_struct_uninit((jl_datatype_t*)core("DivideError")); - jl_overflow_exception = jl_new_struct_uninit((jl_datatype_t*)core("OverflowError")); + jl_fieldoverflow_exception = jl_new_struct_uninit((jl_datatype_t*)core("FieldOverflowError")); jl_undefref_exception = jl_new_struct_uninit((jl_datatype_t*)core("UndefRefError")); jl_undefvarerror_type = (jl_datatype_t*)core("UndefVarError"); jl_interrupt_exception = jl_new_struct_uninit((jl_datatype_t*)core("InterruptException")); diff --git a/src/jltypes.c b/src/jltypes.c index acbb2bdbb3c268..13896b28a6d8f1 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -120,7 +120,7 @@ jl_value_t *jl_segv_exception; #endif JL_DLLEXPORT jl_value_t *jl_diverror_exception; JL_DLLEXPORT jl_value_t *jl_domain_exception; -JL_DLLEXPORT jl_value_t *jl_overflow_exception; +JL_DLLEXPORT jl_value_t *jl_fieldoverflow_exception; JL_DLLEXPORT jl_value_t *jl_undefref_exception; jl_value_t *jl_interrupt_exception; jl_datatype_t *jl_boundserror_type; diff --git a/src/julia.h b/src/julia.h index 64187ba019389e..25107df2dce75c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -528,7 +528,7 @@ extern JL_DLLEXPORT jl_value_t *jl_stackovf_exception; extern JL_DLLEXPORT jl_value_t *jl_memory_exception; extern JL_DLLEXPORT jl_value_t *jl_readonlymemory_exception; extern JL_DLLEXPORT jl_value_t *jl_diverror_exception; -extern JL_DLLEXPORT jl_value_t *jl_overflow_exception; +extern JL_DLLEXPORT jl_value_t *jl_fieldoverflow_exception; extern JL_DLLEXPORT jl_value_t *jl_undefref_exception; extern JL_DLLEXPORT jl_value_t *jl_interrupt_exception; extern JL_DLLEXPORT jl_datatype_t *jl_boundserror_type;