Error -> Defect for defects (#13908)

* Error -> Defect for defects

The distinction between Error and Defect is subjective,
context-dependent and somewhat arbitrary, so when looking at an
exception, it's hard to guess what it is - this happens often when
looking at a `raises` list _without_ opening the corresponding
definition and digging through layers of inheritance.

With the help of a little consistency in naming, it's at least possible
to start disentangling the two error types and the standard lib can set
a good example here.
This commit is contained in:
Jacek Sieka 2020-04-28 19:56:01 +02:00 • committed by GitHub
commit 7d6cbf290a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
92 changed files with 323 additions and 300 deletions

View file

@ -12,10 +12,10 @@
proc raiseOverflow {.compilerproc, noinline.} =
# a single proc to reduce code size to a minimum
sysFatal(OverflowError, "over- or underflow")
sysFatal(OverflowDefect, "over- or underflow")
proc raiseDivByZero {.compilerproc, noinline.} =
sysFatal(DivByZeroError, "division by zero")
sysFatal(DivByZeroDefect, "division by zero")
when defined(builtinOverflow):
# Builtin compiler functions for improved performance
@ -410,16 +410,16 @@ when not declared(mulInt):
# written in other languages.
proc raiseFloatInvalidOp {.compilerproc, noinline.} =
sysFatal(FloatInvalidOpError, "FPU operation caused a NaN result")
sysFatal(FloatInvalidOpDefect, "FPU operation caused a NaN result")
proc nanCheck(x: float64) {.compilerproc, inline.} =
if x != x: raiseFloatInvalidOp()
proc raiseFloatOverflow(x: float64) {.compilerproc, noinline.} =
if x > 0.0:
sysFatal(FloatOverflowError, "FPU operation caused an overflow")
sysFatal(FloatOverflowDefect, "FPU operation caused an overflow")
else:
sysFatal(FloatUnderflowError, "FPU operations caused an underflow")
sysFatal(FloatUnderflowDefect, "FPU operations caused an underflow")
proc infCheck(x: float64) {.compilerproc, inline.} =
if x != 0.0 and x*0.5 == x: raiseFloatOverflow(x)

View file

@ -2,7 +2,7 @@ proc succ*[T: Ordinal](x: T, y = 1): T {.magic: "Succ", noSideEffect.}
## Returns the ``y``-th successor (default: 1) of the value ``x``.
## ``T`` has to be an `ordinal type <#Ordinal>`_.
##
## If such a value does not exist, ``OverflowError`` is raised
## If such a value does not exist, ``OverflowDefect`` is raised
## or a compile time error occurs.
##
## .. code-block:: Nim
@ -14,7 +14,7 @@ proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.}
## Returns the ``y``-th predecessor (default: 1) of the value ``x``.
## ``T`` has to be an `ordinal type <#Ordinal>`_.
##
## If such a value does not exist, ``OverflowError`` is raised
## If such a value does not exist, ``OverflowDefect`` is raised
## or a compile time error occurs.
##
## .. code-block:: Nim
@ -25,7 +25,7 @@ proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.}
proc inc*[T: Ordinal](x: var T, y = 1) {.magic: "Inc", noSideEffect.}
## Increments the ordinal ``x`` by ``y``.
##
## If such a value does not exist, ``OverflowError`` is raised or a compile
## If such a value does not exist, ``OverflowDefect`` is raised or a compile
## time error occurs. This is a short notation for: ``x = succ(x, y)``.
##
## .. code-block:: Nim
@ -36,7 +36,7 @@ proc inc*[T: Ordinal](x: var T, y = 1) {.magic: "Inc", noSideEffect.}
proc dec*[T: Ordinal](x: var T, y = 1) {.magic: "Dec", noSideEffect.}
## Decrements the ordinal ``x`` by ``y``.
##
## If such a value does not exist, ``OverflowError`` is raised or a compile
## If such a value does not exist, ``OverflowDefect`` is raised or a compile
## time error occurs. This is a short notation for: ``x = pred(x, y)``.
##
## .. code-block:: Nim

View file

@ -19,10 +19,10 @@ when not defined(nimHasSinkInference):
{.pragma: nosinks.}
proc raiseAssert*(msg: string) {.noinline, noreturn, nosinks.} =
sysFatal(AssertionError, msg)
sysFatal(AssertionDefect, msg)
proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
# trick the compiler to not list ``AssertionError`` when called
# trick the compiler to not list ``AssertionDefect`` when called
# by ``assert``.
type Hide = proc (msg: string) {.noinline, raises: [], noSideEffect,
tags: [].}
@ -40,9 +40,9 @@ template assertImpl(cond: bool, msg: string, expr: string, enabled: static[bool]
failedAssertImpl(ploc & " `" & expr & "` " & msg)
template assert*(cond: untyped, msg = "") =
## Raises ``AssertionError`` with `msg` if `cond` is false. Note
## that ``AssertionError`` is hidden from the effect system, so it doesn't
## produce ``{.raises: [AssertionError].}``. This exception is only supposed
## Raises ``AssertionDefect`` with `msg` if `cond` is false. Note
## that ``AssertionDefect`` is hidden from the effect system, so it doesn't
## produce ``{.raises: [AssertionDefect].}``. This exception is only supposed
## to be caught by unit testing frameworks.
##
## The compiler may not generate any code at all for ``assert`` if it is
@ -80,7 +80,7 @@ template onFailedAssert*(msg, code: untyped): untyped {.dirty.} =
code
template doAssertRaises*(exception: typedesc, code: untyped) =
## Raises ``AssertionError`` if specified ``code`` does not raise the
## Raises ``AssertionDefect`` if specified ``code`` does not raise the
## specified exception. Example:
##
## .. code-block:: nim

View file

@ -233,10 +233,10 @@ proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
let newBranch = selectBranch(newDiscVal, L, a)
when defined(nimOldCaseObjects):
if newBranch != oldBranch and oldDiscVal != 0:
sysFatal(FieldError, "assignment to discriminant changes object branch")
sysFatal(FieldDefect, "assignment to discriminant changes object branch")
else:
if newBranch != oldBranch:
if oldDiscVal != 0:
sysFatal(FieldError, "assignment to discriminant changes object branch")
sysFatal(FieldDefect, "assignment to discriminant changes object branch")
else:
sysFatal(FieldError, "assignment to discriminant changes object branch; compile with -d:nimOldCaseObjects for a transition period")
sysFatal(FieldDefect, "assignment to discriminant changes object branch; compile with -d:nimOldCaseObjects for a transition period")

View file

@ -347,7 +347,7 @@ template lockChannel(q, action): untyped =
proc sendImpl(q: PRawChannel, typ: PNimType, msg: pointer, noBlock: bool): bool =
if q.mask == ChannelDeadMask:
sysFatal(DeadThreadError, "cannot send message; thread died")
sysFatal(DeadThreadDefect, "cannot send message; thread died")
acquireSys(q.lock)
if q.maxItems > 0:
# Wait until count is less than maxItems

View file

@ -12,34 +12,34 @@ include system/indexerrors
proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
when hostOS == "standalone":
sysFatal(RangeError, "value out of range")
sysFatal(RangeDefect, "value out of range")
else:
sysFatal(RangeError, "value out of range: ", $val)
sysFatal(RangeDefect, "value out of range: ", $val)
proc raiseIndexError3(i, a, b: int) {.compilerproc, noinline.} =
sysFatal(IndexError, formatErrorIndexBound(i, a, b))
sysFatal(IndexDefect, formatErrorIndexBound(i, a, b))
proc raiseIndexError2(i, n: int) {.compilerproc, noinline.} =
sysFatal(IndexError, formatErrorIndexBound(i, n))
sysFatal(IndexDefect, formatErrorIndexBound(i, n))
proc raiseIndexError() {.compilerproc, noinline.} =
sysFatal(IndexError, "index out of bounds")
sysFatal(IndexDefect, "index out of bounds")
proc raiseFieldError(f: string) {.compilerproc, noinline.} =
sysFatal(FieldError, f)
sysFatal(FieldDefect, f)
proc raiseRangeErrorI(i, a, b: BiggestInt) {.compilerproc, noinline.} =
sysFatal(RangeError, "value out of range: " & $i & " notin " & $a & " .. " & $b)
sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b)
proc raiseRangeErrorF(i, a, b: float) {.compilerproc, noinline.} =
sysFatal(RangeError, "value out of range: " & $i & " notin " & $a & " .. " & $b)
sysFatal(RangeDefect, "value out of range: " & $i & " notin " & $a & " .. " & $b)
proc raiseRangeErrorU(i, a, b: uint64) {.compilerproc, noinline.} =
# todo: better error reporting
sysFatal(RangeError, "value out of range")
sysFatal(RangeDefect, "value out of range")
proc raiseObjectConversionError() {.compilerproc, noinline.} =
sysFatal(ObjectConversionError, "invalid object conversion")
sysFatal(ObjectConversionDefect, "invalid object conversion")
proc chckIndx(i, a, b: int): int =
if i >= a and i <= b:
@ -63,24 +63,24 @@ proc chckRangeU(i, a, b: uint64): uint64 {.compilerproc.} =
if i >= a and i <= b:
return i
else:
sysFatal(RangeError, "value out of range")
sysFatal(RangeDefect, "value out of range")
proc chckRangeF(x, a, b: float): float =
if x >= a and x <= b:
return x
else:
when hostOS == "standalone":
sysFatal(RangeError, "value out of range")
sysFatal(RangeDefect, "value out of range")
else:
sysFatal(RangeError, "value out of range: ", $x)
sysFatal(RangeDefect, "value out of range: ", $x)
proc chckNil(p: pointer) =
if p == nil:
sysFatal(NilAccessError, "attempt to write to a nil address")
sysFatal(NilAccessDefect, "attempt to write to a nil address")
proc chckNilDisp(p: pointer) {.compilerproc.} =
if p == nil:
sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
sysFatal(NilAccessDefect, "cannot dispatch; dispatcher is nil")
when not defined(nimV2):
@ -90,12 +90,12 @@ when not defined(nimV2):
if x == subclass: return # optimized fast path
while x != subclass:
if x == nil:
sysFatal(ObjectConversionError, "invalid object conversion")
sysFatal(ObjectConversionDefect, "invalid object conversion")
x = x.base
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
if a != b:
sysFatal(ObjectAssignmentError, "invalid object assignment")
sysFatal(ObjectAssignmentDefect, "invalid object assignment")
type ObjCheckCache = array[0..1, PNimType]
@ -130,4 +130,4 @@ when not defined(nimV2):
when defined(nimV2):
proc raiseObjectCaseTransition() {.compilerproc.} =
sysFatal(FieldError, "assignment to discriminant changes object branch")
sysFatal(FieldDefect, "assignment to discriminant changes object branch")

View file

@ -32,10 +32,10 @@ const
proc quitOrDebug() {.noreturn, importc: "abort", header: "<stdlib.h>", nodecl.}
proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
sysFatal(ReraiseError, "exception handling is not available")
sysFatal(ReraiseDefect, "exception handling is not available")
proc reraiseException() {.compilerRtl.} =
sysFatal(ReraiseError, "no exception to reraise")
sysFatal(ReraiseDefect, "no exception to reraise")
proc writeStackTrace() = discard
@ -43,4 +43,4 @@ proc unsetControlCHook() = discard
proc setControlCHook(hook: proc () {.noconv.}) = discard
proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
sysFatal(ReraiseError, "exception handling is not available")
sysFatal(ReraiseDefect, "exception handling is not available")

View file

@ -62,19 +62,19 @@ type
## Raised if a dynamic library could not be loaded.
ResourceExhaustedError* = object of CatchableError ## \
## Raised if a resource request could not be fulfilled.
ArithmeticError* = object of Defect ## \
ArithmeticDefect* = object of Defect ## \
## Raised if any kind of arithmetic error occurred.
DivByZeroError* = object of ArithmeticError ## \
DivByZeroDefect* = object of ArithmeticDefect ## \
## Raised for runtime integer divide-by-zero errors.
OverflowError* = object of ArithmeticError ## \
OverflowDefect* = object of ArithmeticDefect ## \
## Raised for runtime integer overflows.
##
## This happens for calculations whose results are too large to fit in the
## provided bits.
AccessViolationError* = object of Defect ## \
AccessViolationDefect* = object of Defect ## \
## Raised for invalid memory access errors
AssertionError* = object of Defect ## \
AssertionDefect* = object of Defect ## \
## Raised when assertion is proved wrong.
##
## Usually the result of using the `assert() template
@ -87,54 +87,77 @@ type
## Mostly used by the `tables <tables.html>`_ module, it can also be raised
## by other collection modules like `sets <sets.html>`_ or `strtabs
## <strtabs.html>`_.
OutOfMemError* = object of Defect ## \
OutOfMemDefect* = object of Defect ## \
## Raised for unsuccessful attempts to allocate memory.
IndexError* = object of Defect ## \
IndexDefect* = object of Defect ## \
## Raised if an array index is out of bounds.
FieldError* = object of Defect ## \
FieldDefect* = object of Defect ## \
## Raised if a record field is not accessible because its discriminant's
## value does not fit.
RangeError* = object of Defect ## \
RangeDefect* = object of Defect ## \
## Raised if a range check error occurred.
StackOverflowError* = object of Defect ## \
StackOverflowDefect* = object of Defect ## \
## Raised if the hardware stack used for subroutine calls overflowed.
ReraiseError* = object of Defect ## \
ReraiseDefect* = object of Defect ## \
## Raised if there is no exception to reraise.
ObjectAssignmentError* = object of Defect ## \
ObjectAssignmentDefect* = object of Defect ## \
## Raised if an object gets assigned to its parent's object.
ObjectConversionError* = object of Defect ## \
ObjectConversionDefect* = object of Defect ## \
## Raised if an object is converted to an incompatible object type.
## You can use ``of`` operator to check if conversion will succeed.
FloatingPointError* = object of Defect ## \
FloatingPointDefect* = object of Defect ## \
## Base class for floating point exceptions.
FloatInvalidOpError* = object of FloatingPointError ## \
FloatInvalidOpDefect* = object of FloatingPointDefect ## \
## Raised by invalid operations according to IEEE.
##
## Raised by ``0.0/0.0``, for example.
FloatDivByZeroError* = object of FloatingPointError ## \
FloatDivByZeroDefect* = object of FloatingPointDefect ## \
## Raised by division by zero.
##
## Divisor is zero and dividend is a finite nonzero number.
FloatOverflowError* = object of FloatingPointError ## \
FloatOverflowDefect* = object of FloatingPointDefect ## \
## Raised for overflows.
##
## The operation produced a result that exceeds the range of the exponent.
FloatUnderflowError* = object of FloatingPointError ## \
FloatUnderflowDefect* = object of FloatingPointDefect ## \
## Raised for underflows.
##
## The operation produced a result that is too small to be represented as a
## normal number.
FloatInexactError* = object of FloatingPointError ## \
FloatInexactDefect* = object of FloatingPointDefect ## \
## Raised for inexact results.
##
## The operation produced a result that cannot be represented with infinite
## precision -- for example: ``2.0 / 3.0, log(1.1)``
##
## **Note**: Nim currently does not detect these!
DeadThreadError* = object of Defect ## \
DeadThreadDefect* = object of Defect ## \
## Raised if it is attempted to send a message to a dead thread.
NilAccessError* = object of Defect ## \
NilAccessDefect* = object of Defect ## \
## Raised on dereferences of ``nil`` pointers.
##
## This is only raised if the `segfaults module <segfaults.html>`_ was imported!
ArithmeticError* {.deprecated: "See corresponding Defect".} = ArithmeticDefect
DivByZeroError* {.deprecated: "See corresponding Defect".} = ArithmeticDefect
OverflowError* {.deprecated: "See corresponding Defect".} = OverflowDefect
AccessViolationError* {.deprecated: "See corresponding Defect".} = AccessViolationDefect
AssertionError* {.deprecated: "See corresponding Defect".} = AssertionDefect
OutOfMemError* {.deprecated: "See corresponding Defect".} = OutOfMemDefect
IndexError* {.deprecated: "See corresponding Defect".} = IndexDefect
FieldError* {.deprecated: "See corresponding Defect".} = FieldDefect
RangeError* {.deprecated: "See corresponding Defect".} = RangeDefect
StackOverflowError* {.deprecated: "See corresponding Defect".} = StackOverflowDefect
ReraiseError* {.deprecated: "See corresponding Defect".} = ReraiseDefect
ObjectAssignmentError* {.deprecated: "See corresponding Defect".} = ObjectAssignmentDefect
ObjectConversionError* {.deprecated: "See corresponding Defect".} = ObjectConversionDefect
FloatingPointError* {.deprecated: "See corresponding Defect".} = FloatingPointDefect
FloatInvalidOpError* {.deprecated: "See corresponding Defect".} = FloatInvalidOpDefect
FloatDivByZeroError* {.deprecated: "See corresponding Defect".} = FloatDivByZeroDefect
FloatOverflowError* {.deprecated: "See corresponding Defect".} = FloatOverflowDefect
FloatUnderflowError* {.deprecated: "See corresponding Defect".} = FloatUnderflowDefect
FloatInexactError* {.deprecated: "See corresponding Defect".} = FloatInexactDefect
DeadThreadError* {.deprecated: "See corresponding Defect".} = DeadThreadDefect
NilAccessError* {.deprecated: "See corresponding Defect".} = NilAccessDefect

View file

@ -483,7 +483,7 @@ proc raiseException(e: sink(ref Exception), ename: cstring) {.compilerRtl.} =
proc reraiseException() {.compilerRtl.} =
if currException == nil:
sysFatal(ReraiseError, "no exception to reraise")
sysFatal(ReraiseDefect, "no exception to reraise")
else:
when gotoBasedExceptions:
inc nimInErrorMode

View file

@ -844,7 +844,7 @@ when not defined(useNimRtl):
inc(gch.recGcLock)
proc GC_enable() =
if gch.recGcLock <= 0:
raise newException(AssertionError,
raise newException(AssertionDefect,
"API usage error: GC_enable called but GC is already enabled")
dec(gch.recGcLock)

View file

@ -496,7 +496,7 @@ when not defined(useNimRtl):
inc(gch.recGcLock)
proc GC_enable() =
if gch.recGcLock <= 0:
raise newException(AssertionError,
raise newException(AssertionDefect,
"API usage error: GC_enable called but GC is already enabled")
dec(gch.recGcLock)

View file

@ -12,10 +12,10 @@
proc raiseOverflow {.compilerproc, noinline.} =
# a single proc to reduce code size to a minimum
sysFatal(OverflowError, "over- or underflow")
sysFatal(OverflowDefect, "over- or underflow")
proc raiseDivByZero {.compilerproc, noinline.} =
sysFatal(DivByZeroError, "division by zero")
sysFatal(DivByZeroDefect, "division by zero")
{.pragma: nimbaseH, importc, nodecl, noSideEffect, compilerproc.}
@ -123,10 +123,10 @@ divImplFallback(nimDivInt, int)
divImplFallback(nimDivInt64, int64)
proc raiseFloatInvalidOp {.compilerproc, noinline.} =
sysFatal(FloatInvalidOpError, "FPU operation caused a NaN result")
sysFatal(FloatInvalidOpDefect, "FPU operation caused a NaN result")
proc raiseFloatOverflow(x: float64) {.compilerproc, noinline.} =
if x > 0.0:
sysFatal(FloatOverflowError, "FPU operation caused an overflow")
sysFatal(FloatOverflowDefect, "FPU operation caused an overflow")
else:
sysFatal(FloatUnderflowError, "FPU operations caused an underflow")
sysFatal(FloatUnderflowDefect, "FPU operations caused an underflow")

View file

@ -142,7 +142,7 @@ proc raiseException(e: ref Exception, ename: cstring) {.
proc reraiseException() {.compilerproc, asmNoStackFrame.} =
if lastJSError == nil:
raise newException(ReraiseError, "no exception to reraise")
raise newException(ReraiseDefect, "no exception to reraise")
else:
if excHandler == 0:
if isNimException():
@ -151,19 +151,19 @@ proc reraiseException() {.compilerproc, asmNoStackFrame.} =
asm "throw lastJSError;"
proc raiseOverflow {.exportc: "raiseOverflow", noreturn, compilerproc.} =
raise newException(OverflowError, "over- or underflow")
raise newException(OverflowDefect, "over- or underflow")
proc raiseDivByZero {.exportc: "raiseDivByZero", noreturn, compilerproc.} =
raise newException(DivByZeroError, "division by zero")
raise newException(DivByZeroDefect, "division by zero")
proc raiseRangeError() {.compilerproc, noreturn.} =
raise newException(RangeError, "value out of range")
raise newException(RangeDefect, "value out of range")
proc raiseIndexError(i, a, b: int) {.compilerproc, noreturn.} =
raise newException(IndexError, formatErrorIndexBound(int(i), int(a), int(b)))
raise newException(IndexDefect, formatErrorIndexBound(int(i), int(a), int(b)))
proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
raise newException(FieldError, f)
raise newException(FieldDefect, f)
proc setConstr() {.varargs, asmNoStackFrame, compilerproc.} =
asm """
@ -524,7 +524,7 @@ proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b
proc chckNilDisp(p: pointer) {.compilerproc.} =
if p == nil:
sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
sysFatal(NilAccessDefect, "cannot dispatch; dispatcher is nil")
include "system/hti"
@ -663,7 +663,7 @@ proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
if x == subclass: return # optimized fast path
while x != subclass:
if x == nil:
raise newException(ObjectConversionError, "invalid object conversion")
raise newException(ObjectConversionDefect, "invalid object conversion")
x = x.base
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =

View file

@ -191,4 +191,4 @@ proc isObj(obj: PNimType, subclass: cstring): bool {.compilerRtl, inl.} =
proc chckObj(obj: PNimType, subclass: cstring) {.compilerRtl.} =
# checks if obj is of type subclass:
if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion")
if not isObj(obj, subclass): sysFatal(ObjectConversionDefect, "invalid object conversion")