Skip to content

Commit e580716

Browse files
committed
InexactError->InvalidValueError, with more informative backtraces
1 parent f988566 commit e580716

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+212
-161
lines changed

base/bool.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
## boolean conversions ##
44

55
convert(::Type{Bool}, x::Bool) = x
6-
convert(::Type{Bool}, x::Float16) = x==0 ? false : x==1 ? true : throw(InexactError())
7-
convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError())
6+
convert(::Type{Bool}, x::Float16) = x==0 ? false : x==1 ? true : throw(InvalidValueError(:convert, Bool, x))
7+
convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InvalidValueError(:convert, Bool, x))
88

99
# promote Bool to any other numeric type
1010
promote_rule(::Type{Bool}, ::Type{T}) where {T<:Number} = T

base/boot.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,9 @@ export
132132
Char, DirectIndexString, AbstractString, String, IO,
133133
# errors
134134
ErrorException, BoundsError, DivideError, DomainError, Exception, InexactError,
135-
InterruptException, OutOfMemoryError, ReadOnlyMemoryError, OverflowError,
136-
StackOverflowError, SegmentationFault, UndefRefError, UndefVarError, TypeError,
135+
InterruptException, InvalidValueError, OutOfMemoryError, ReadOnlyMemoryError,
136+
OverflowError, StackOverflowError, SegmentationFault, UndefRefError, UndefVarError,
137+
TypeError,
137138
# AST representation
138139
Expr, GotoNode, LabelNode, LineNumberNode, QuoteNode,
139140
GlobalRef, NewvarNode, SSAValue, Slot, SlotNumber, TypedSlot,
@@ -221,6 +222,13 @@ mutable struct TypeError <: Exception
221222
expected::Type
222223
got
223224
end
225+
struct InvalidValueError <: Exception
226+
func::Symbol
227+
T::Type
228+
val
229+
230+
InvalidValueError(f::Symbol, T::ANY, val::ANY) = (@_noinline_meta; new(f, T, val))
231+
end
224232

225233
abstract type DirectIndexString <: AbstractString end
226234

base/complex.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const Complex32 = Complex{Float16}
2121
convert(::Type{Complex{T}}, x::Real) where {T<:Real} = Complex{T}(x,0)
2222
convert(::Type{Complex{T}}, z::Complex) where {T<:Real} = Complex{T}(real(z),imag(z))
2323
convert(::Type{T}, z::Complex) where {T<:Real} =
24-
isreal(z) ? convert(T,real(z)) : throw(InexactError())
24+
isreal(z) ? convert(T,real(z)) : throw(InvalidValueError(:convert, T, z))
2525

2626
convert(::Type{Complex}, z::Complex) = z
2727
convert(::Type{Complex}, x::Real) = Complex(x)

base/dates/arithmetic.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
1515
The addition of a `Date` with a `Time` produces a `DateTime`. The hour, minute, second, and millisecond parts of
1616
the `Time` are used along with the year, month, and day of the `Date` to create the new `DateTime`.
17-
Non-zero microseconds or nanoseconds in the `Time` type will result in an `InexactError` being thrown.
17+
Non-zero microseconds or nanoseconds in the `Time` type will result in an `InvalidValueError` being thrown.
1818
"""
1919
function (+)(dt::Date, t::Time)
20-
(microsecond(t) > 0 || nanosecond(t) > 0) && throw(InexactError())
20+
(microsecond(t) > 0 || nanosecond(t) > 0) && throw(InvalidValueError(:+, DateTime, t))
2121
y, m, d = yearmonthday(dt)
2222
return DateTime(y, m, d, hour(t), minute(t), second(t), millisecond(t))
2323
end

base/dates/periods.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ const FixedPeriod = Union{Week, Day, Hour, Minute, Second, Millisecond, Microsec
400400
# like div but throw an error if remainder is nonzero
401401
function divexact(x, y)
402402
q, r = divrem(x, y)
403-
r == 0 || throw(InexactError())
403+
r == 0 || throw(InvalidValueError(:divexact, Int, x/y))
404404
return q
405405
end
406406

@@ -415,7 +415,7 @@ for i = 1:length(fixedperiod_conversions)
415415
vmax = typemax(Int64) ÷ N
416416
vmin = typemin(Int64) ÷ N
417417
@eval function Base.convert(::Type{$T}, x::$Tc)
418-
$vmin value(x) $vmax || throw(InexactError())
418+
$vmin value(x) $vmax || throw(InvalidValueError(:convert, $T, x))
419419
return $T(value(x) * $N)
420420
end
421421
end
@@ -432,7 +432,7 @@ end
432432
const OtherPeriod = Union{Month, Year}
433433
let vmax = typemax(Int64) ÷ 12, vmin = typemin(Int64) ÷ 12
434434
@eval function Base.convert(::Type{Month}, x::Year)
435-
$vmin value(x) $vmax || throw(InexactError())
435+
$vmin value(x) $vmax || throw(InvalidValueError(:convert, Month, x))
436436
Month(value(x) * 12)
437437
end
438438
end

base/distributed/pmap.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ Example: On errors, retry `f` on an element a maximum of 3 times without any del
9090
pmap(f, c; retry_delays = zeros(3))
9191
```
9292
93-
Example: Retry `f` only if the exception is not of type `InexactError`, with exponentially increasing
94-
delays up to 3 times. Return a `NaN` in place for all `InexactError` occurrences.
93+
Example: Retry `f` only if the exception is not of type `InvalidValueError`, with exponentially increasing
94+
delays up to 3 times. Return a `NaN` in place for all `InvalidValueError` occurrences.
9595
```julia
96-
pmap(f, c; on_error = e->(isa(e, InexactError) ? NaN : rethrow(e)), retry_delays = ExponentialBackOff(n = 3))
96+
pmap(f, c; on_error = e->(isa(e, InvalidValueError) ? NaN : rethrow(e)), retry_delays = ExponentialBackOff(n = 3))
9797
```
9898
"""
9999
function pmap(p::AbstractWorkerPool, f, c; distributed=true, batch_size=1, on_error=nothing,

base/docs/helpdb/Base.jl

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ ReadOnlyMemoryError
359359
`ceil(x)` returns the nearest integral value of the same type as `x` that is greater than or
360360
equal to `x`.
361361
362-
`ceil(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is not
362+
`ceil(T, x)` converts the result to type `T`, throwing an `InvalidValueError` if the value is not
363363
representable.
364364
365365
`digits` and `base` work as for [`round`](@ref).
@@ -646,7 +646,7 @@ Mmap.Anonymous
646646
`floor(x)` returns the nearest integral value of the same type as `x` that is less than or
647647
equal to `x`.
648648
649-
`floor(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is
649+
`floor(T, x)` converts the result to type `T`, throwing an `InvalidValueError` if the value is
650650
not representable.
651651
652652
`digits` and `base` work as for [`round`](@ref).
@@ -878,7 +878,7 @@ typeof
878878
`trunc(x)` returns the nearest integral value of the same type as `x` whose absolute value
879879
is less than or equal to `x`.
880880
881-
`trunc(T, x)` converts the result to type `T`, throwing an `InexactError` if the value is
881+
`trunc(T, x)` converts the result to type `T`, throwing an `InvalidValueError` if the value is
882882
not representable.
883883
884884
`digits` and `base` work as for [`round`](@ref).
@@ -1374,6 +1374,13 @@ Type conversion cannot be done exactly.
13741374
"""
13751375
InexactError
13761376

1377+
"""
1378+
InvalidValueError(name::Symbol, T, val)
1379+
1380+
Cannot convert `val` to type `T` in a method of function `name`.
1381+
"""
1382+
InvalidValueError
1383+
13771384
"""
13781385
typemax(T)
13791386
@@ -1946,7 +1953,7 @@ done
19461953
19471954
Convert `x` to a value of type `T`.
19481955
1949-
If `T` is an `Integer` type, an [`InexactError`](@ref) will be raised if `x`
1956+
If `T` is an `Integer` type, an [`InvalidValueError`](@ref) will be raised if `x`
19501957
is not representable by `T`, for example if `x` is not integer-valued, or is outside the
19511958
range supported by `T`.
19521959
@@ -1955,9 +1962,9 @@ julia> convert(Int, 3.0)
19551962
3
19561963
19571964
julia> convert(Int, 3.5)
1958-
ERROR: InexactError()
1965+
ERROR: InvalidValueError: convert(Int64, 3.5::Float64)
19591966
Stacktrace:
1960-
[1] convert(::Type{Int64}, ::Float64) at ./float.jl:679
1967+
[1] convert(::Type{Int64}, ::Float64) at ./float.jl:680
19611968
```
19621969
19631970
If `T` is a `AbstractFloat` or `Rational` type,

base/float.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -649,14 +649,14 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn
649649
if $(Tf(typemin(Ti))-one(Tf)) < x < $(Tf(typemax(Ti))+one(Tf))
650650
return unsafe_trunc($Ti,x)
651651
else
652-
throw(InexactError())
652+
throw(InvalidValueError(:trunc, $Ti, x))
653653
end
654654
end
655655
function convert(::Type{$Ti}, x::$Tf)
656656
if ($(Tf(typemin(Ti))) <= x <= $(Tf(typemax(Ti)))) && (trunc(x) == x)
657657
return unsafe_trunc($Ti,x)
658658
else
659-
throw(InexactError())
659+
throw(InvalidValueError(:convert, $Ti, x))
660660
end
661661
end
662662
end
@@ -670,14 +670,14 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn
670670
if $(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti)))
671671
return unsafe_trunc($Ti,x)
672672
else
673-
throw(InexactError())
673+
throw(InvalidValueError(:trunc, $Ti, x))
674674
end
675675
end
676676
function convert(::Type{$Ti}, x::$Tf)
677677
if ($(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti)))) && (trunc(x) == x)
678678
return unsafe_trunc($Ti,x)
679679
else
680-
throw(InexactError())
680+
throw(InvalidValueError(:convert, $Ti, x))
681681
end
682682
end
683683
end

base/floatfuncs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ The optional [`RoundingMode`](@ref) argument will change how the number gets
6363
rounded.
6464
6565
`round(T, x, [r::RoundingMode])` converts the result to type `T`, throwing an
66-
[`InexactError`](@ref) if the value is not representable.
66+
[`InvalidValueError`](@ref) if the value is not representable.
6767
6868
`round(x, digits)` rounds to the specified number of digits after the decimal place (or
6969
before if negative). `round(x, digits, base)` rounds using a base other than 10.

base/gmp.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,12 @@ convert(::Type{BigInt}, x::Bool) = BigInt(UInt(x))
231231
unsafe_trunc(::Type{BigInt}, x::Union{Float32,Float64}) = MPZ.set_d(x)
232232

233233
function convert(::Type{BigInt}, x::Union{Float32,Float64})
234-
isinteger(x) || throw(InexactError())
234+
isinteger(x) || throw(InvalidValueError(:convert, BigInt, x))
235235
unsafe_trunc(BigInt,x)
236236
end
237237

238238
function trunc(::Type{BigInt}, x::Union{Float32,Float64})
239-
isfinite(x) || throw(InexactError())
239+
isfinite(x) || throw(InvalidValueError(:trunc, BigInt, x))
240240
unsafe_trunc(BigInt,x)
241241
end
242242

@@ -287,7 +287,7 @@ function convert(::Type{T}, x::BigInt) where T<:Unsigned
287287
if sizeof(T) < sizeof(Limb)
288288
convert(T, convert(Limb,x))
289289
else
290-
0 <= x.size <= cld(sizeof(T),sizeof(Limb)) || throw(InexactError())
290+
0 <= x.size <= cld(sizeof(T),sizeof(Limb)) || throw(InvalidValueError(:convert, T, x))
291291
x % T
292292
end
293293
end
@@ -298,9 +298,9 @@ function convert(::Type{T}, x::BigInt) where T<:Signed
298298
SLimb = typeof(Signed(one(Limb)))
299299
convert(T, convert(SLimb, x))
300300
else
301-
0 <= n <= cld(sizeof(T),sizeof(Limb)) || throw(InexactError())
301+
0 <= n <= cld(sizeof(T),sizeof(Limb)) || throw(InvalidValueError(:convert, T, x))
302302
y = x % T
303-
ispos(x) (y > 0) && throw(InexactError()) # catch overflow
303+
ispos(x) (y > 0) && throw(InvalidValueError(:convert, T, x)) # catch overflow
304304
y
305305
end
306306
end

0 commit comments

Comments
 (0)