Difference between revisions of "DIP33"
Kyllingstad (talk | contribs) |
Kyllingstad (talk | contribs) |
||
Line 120: | Line 120: | ||
if (!exists(path)) | if (!exists(path)) | ||
throw new FilesystemException("File not found: "~path); | throw new FilesystemException("File not found: "~path); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === RangeError === | ||
+ | <syntaxhighlight lang="d"> | ||
+ | class RangeError : Error { } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | This error is thrown on illegal range operations. Examples include when an array index is out of bounds, when <code>front</code> or <code>popFront()</code> is called on an <code>empty</code> range, etc. | ||
+ | |||
+ | <syntaxhighlight lang="d"> | ||
+ | struct MyRange(T) | ||
+ | { | ||
+ | @property bool empty() { ... } | ||
+ | @property T front() | ||
+ | { | ||
+ | if (empty) throw new RangeError("front called on empty range"); | ||
+ | ... | ||
+ | } | ||
+ | void popFront() | ||
+ | { | ||
+ | if (empty) throw new RangeError("popFront() called on empty range"); | ||
+ | ... | ||
+ | } | ||
+ | ... | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Revision as of 07:23, 1 April 2013
This DIP is currently under construction. Please come back later.
Title: | A new exception hierarchy |
---|---|
DIP: | 33 |
Version: | 1 |
Status: | Draft |
Created: | 2013-04-01 |
Last Modified: | 2013-04-01 |
Author: | Lars T. Kyllingstad |
Links: |
Contents
[hide]Abstract
This is a proposal for a new exception hierarchy for Druntime and Phobos.
Rationale
Overview
The following is an outline of the exceptions in the hierarchy, and how they are related to each other. Deeper levels are subclasses of those above.
Throwable
Error
AssertError
InvalidArgumentError
RangeError
Exception
ConversionException
Exception
EncodingException
FilesystemException
IOException
NetworkException
ParseException
DocParseException
ProcessException
SystemException
ErrnoException
WinAPIException
ThreadException
OutOfMemory
Top-level classes
Strictly speaking, Throwable
is of course the (only) top-level exception class. Here, however, we discuss its direct descendants, from which all other exception classes derive.
Error
class Error : Throwable { }
Error
and its subclasses are used to signal programming errors. If an Error
is thrown, it means that there is something wrong with how the program is constructed. Examples include array index out of bounds, invalid function arguments, etc. Importantly, it should always be possible to avoid an Error
by design.
In general, Error
s should not be caught, primarily because they indicate that the program logic is compromised, and that the program may therefore be in an invalid state from which there is no recovery. Furthermore, one cannot rely on them being thrown at all. For example, assert
statements and array bounds checks, which both trigger Error
s, may be disabled by compiler switches.
If an Error
must be caught, it is recommended to do so at a very high level (e.g. in main()
), and then only to perform critical cleanup work before terminating the program gracefully.
Exception
class Exception : Throwable { }
Exception
and its descendants are used to signal normal runtime errors. These are exceptional circumstances that the programmer cannot be expected to avoid by design. Examples include file not found, problems with parsing a document, system errors, etc.
OutOfMemory
class OutOfMemory : Throwable { }
This exception is thrown on an attempt to allocate more memory than what is currently available for the program. Strictly speaking, this is not an Error
, as the programmer cannot reasonably be expected to check memory availability before each allocation. However, is not desirable to catch it along with normal Exception
s either, as an out-of-memory condition requires special treatment. Therefore, this DIP places OutOfMemory
at the top level of the hierarchy, alongside Error
and Exception
.
Errors
Here follows a more detailed description of the various Error
subclasses.
AssertError
class AssertError : Error { }
This error is thrown when an assert
statement fails.
InvalidArgumentError
class InvalidArgumentError : Error { }
This error is thrown when one or more function arguments are invalid. Since it is an Error
, it should only be used to signal errors that the programmer (i.e. the user of the function in question) can reasonably be expected to avoid, and which are not too costly to check. Circumstances that are out of the programmer's control, or which are so expensive to verify that it is undesirable to have them checked by both the caller and the callee, should be signalled with an Exception
instead.
void processFile(string path)
{
// The following is an acceptable use of InvalidArgumentError,
// as the function should never be given an empty path, and the
// check is trivial.
if (path.empty)
throw new InvalidArgumentError("path is empty");
// The function caller should not be expected to verify file existence.
// Firstly, it could change between the time it is checked and the time
// the function is called, and secondly, it requires filesystem lookup
// which is a relatively expensive operation.
if (!exists(path))
throw new FilesystemException("File not found: "~path);
}
RangeError
class RangeError : Error { }
This error is thrown on illegal range operations. Examples include when an array index is out of bounds, when front
or popFront()
is called on an empty
range, etc.
struct MyRange(T)
{
@property bool empty() { ... }
@property T front()
{
if (empty) throw new RangeError("front called on empty range");
...
}
void popFront()
{
if (empty) throw new RangeError("popFront() called on empty range");
...
}
...
}
Copyright
This document has been placed in the Public Domain.