The D Programming Language

This module defines functions related to exceptions and general error handling. It also defines functions intended to aid in unit testing.

Synopsis of some of std. exception's functions:

string synopsis()
{
    FILE* f = enforce(fopen("some/file"));
    // f is not null from here on

    FILE* g = enforceEx!WriteException(fopen("some/other/file", "w"));
    // g is not null from here on


    Exception e = collectException(write(g, readln(f)));
    if (e)
    {
        ... an exception occurred...
        ... We have the exception to play around with...
    }

    string msg = collectExceptionMsg(write(g, readln(f)));
    if (msg)
    {
        ... an exception occurred...
        ... We have the message from the exception but not the exception...
    }

    char[] line;
    enforce(readln(f, line));
    return assumeUnique(line);
}

License
Boost License 1.0
Authors
Andrei Alexandrescu and Jonathan M Davis
Source:
std/exception.d

void  assertNotThrown(T : Throwable = Exception, E)(lazy E expression, string msg = null, string file = __FILE__, size_t line = __LINE__);

Asserts that the given expression does not throw the given type of Throwable. If a Throwable of the given type is thrown, it is caught and does not escape  assertNotThrown. Rather, an AssertError is thrown. However, any other Throwables will escape.

Parameters
T The Throwable to test for.
E expression The expression to test.
string msg Optional message to output on test failure. If msg is empty, and the thrown exception has a non-empty msg field, the exception's msg field will be output on test failure.
string file The file where the error occurred. Defaults to _FILE__.
size_t line The line where the error occurred. Defaults to _LINE__.
Throws
AssertError if the given Throwable is thrown.
Examples
    assertNotThrown!StringException(enforceEx!StringException(true, "Error!"));

    //Exception is the default.

    assertNotThrown(enforceEx!StringException(true, "Error!"));

    assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
               enforceEx!StringException(false, "Error!"))) ==
           `assertNotThrown failed: StringException was thrown: Error!`);

void  assertThrown(T : Throwable = Exception, E)(lazy E expression, string msg = null, string file = __FILE__, size_t line = __LINE__);

Asserts that the given expression throws the given type of Throwable. The Throwable is caught and does not escape  assertThrown. However, any other Throwables will escape, and if no Throwable of the given type is thrown, then an AssertError is thrown.

Parameters
T The Throwable to test for.
E expression The expression to test.
string msg Optional message to output on test failure.
string file The file where the error occurred. Defaults to _FILE__.
size_t line The line where the error occurred. Defaults to _LINE__.
Throws
AssertError if the given Throwable is not thrown.
Examples
    assertThrown!StringException(enforceEx!StringException(false, "Error!"));

    //Exception is the default.

    assertThrown(enforceEx!StringException(false, "Error!"));

    assert(collectExceptionMsg!AssertError(assertThrown!StringException(
               enforceEx!StringException(true, "Error!"))) ==
           `assertThrown failed: No StringException was thrown.`);

T  enforce(T)(T value, lazy const(char)[] msg = null, string file = __FILE__, size_t line = __LINE__);

If !!value is true, value is returned. Otherwise, new Exception(msg) is thrown.

Note:
 enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program. That is what assert is for. Also, do not use  enforce inside of contracts (i.e. inside of in and out blocks and invariants), because they will be compiled out when compiling with -release. Use assert in contracts.
Example:
auto f = enforce(fopen("data.txt"));
auto line = readln(f);
enforce(line.length, "Expected a non-empty line.");

T  enforce(T, string file, size_t line = __LINE__)(T value, lazy const(char)[] msg = null);

Scheduled for deprecation in January 2013. If passing the file or line number explicitly, please use the version of  enforce which takes them as function arguments. Taking them as template arguments causes unnecessary template bloat.


T  enforce(T, Dg, string file = __FILE__, size_t line = __LINE__)(T value, scope Dg dg) if (isSomeFunction!Dg && is(typeof(dg())));

If !!value is true, value is returned. Otherwise, the given delegate is called.

The whole safety and purity are inferred from Dg's safety and purity.


T  enforce(T)(T value, lazy Throwable ex);

If !!value is true, value is returned. Otherwise, ex is thrown.

Example:
auto f = enforce(fopen("data.txt"));
auto line = readln(f);
enforce(line.length, new IOException); // expect a non-empty line


T  errnoEnforce(T, string file = __FILE__, size_t line = __LINE__)(T value, lazy string msg = null);

If !!value is true, value is returned. Otherwise, new ErrnoException(msg) is thrown. ErrnoException assumes that the last operation set errno to an error code.

Example:
auto f = errnoEnforce(fopen("data.txt"));
auto line = readln(f);
enforce(line.length); // expect a non-empty line


template  enforceEx(E) if (is(typeof(new E("", "phobos\\std\\exception.d", 522))))

If !!value is true, value is returned. Otherwise, new E(msg, file, line) is thrown. Or if E doesn't take a message and can be constructed with new E(file, line), then new E(file, line) will be thrown.

Example:
auto f = enforceEx!FileMissingException(fopen("data.txt"));
auto line = readln(f);
enforceEx!DataCorruptionException(line.length);

T  collectException(T = Exception, E)(lazy E expression, ref E result);

Catches and returns the exception thrown from the given expression. If no exception is thrown, then null is returned and result is set to the result of the expression.

Note that while  collectException can be used to collect any Throwable and not just Exceptions, it is generally ill-advised to catch anything that is neither an Exception nor a type derived from Exception. So, do not use  collectException to collect non-Exceptions unless you're sure that that's what you really want to do.

Parameters
T The type of exception to catch.
E expression The expression which may throw an exception.
E result The result of the expression if no exception is thrown.
Examples
    int b;
    int foo() { throw new Exception("blah"); }
    assert(collectException(foo(), b));

    int[] a = new int[3];
    import core.exception : RangeError;
    assert(collectException!RangeError(a[4], b));

T  collectException(T : Throwable = Exception, E)(lazy E expression);

Catches and returns the exception thrown from the given expression. If no exception is thrown, then null is returned. E can be void.

Note that while  collectException can be used to collect any Throwable and not just Exceptions, it is generally ill-advised to catch anything that is neither an Exception nor a type derived from Exception. So, do not use  collectException to collect non-Exceptions unless you're sure that that's what you really want to do.

Parameters
T The type of exception to catch.
E expression The expression which may throw an exception.

string  collectExceptionMsg(T = Exception, E)(lazy E expression);

Catches the exception thrown from the given expression and returns the msg property of that exception. If no exception is thrown, then null is returned. E can be void.

If an exception is thrown but it has an empty message, then emptyExceptionMsg is returned.

Note that while  collectExceptionMsg can be used to collect any Throwable and not just Exceptions, it is generally ill-advised to catch anything that is neither an Exception nor a type derived from Exception. So, do not use  collectExceptionMsg to collect non-Exceptions unless you're sure that that's what you really want to do.

Parameters
T The type of exception to catch.
E expression The expression which may throw an exception.
Examples
    void throwFunc() { throw new Exception("My Message."); }
    assert(collectExceptionMsg(throwFunc()) == "My Message.");

    void nothrowFunc() {}
    assert(collectExceptionMsg(nothrowFunc()) is null);

    void throwEmptyFunc() { throw new Exception(""); }
    assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg);

Value that collectExceptionMsg returns when it catches an exception with an empty exception message.


pure nothrow immutable(T)[]  assumeUnique(T)(T[] array);
pure nothrow immutable(T)[]  assumeUnique(T)(ref T[] array);

Casts a mutable array to an immutable array in an idiomatic manner. Technically,  assumeUnique just inserts a cast, but its name documents assumptions on the part of the caller.  assumeUnique(arr) should only be called when there are no more active mutable aliases to elements of arr. To strenghten this assumption,  assumeUnique(arr) also clears arr before returning. Essentially  assumeUnique(arr) indicates commitment from the caller that there is no more mutable access to any of arr's elements (transitively), and that all future accesses will be done through the immutable array returned by  assumeUnique.

Typically,  assumeUnique is used to return arrays from functions that have allocated and built them.

Example:
string letters()
{
  char[] result = new char['z' - 'a' + 1];
  foreach (i, ref e; result)
  {
    e = 'a' + i;
  }
  return assumeUnique(result);
}


The use in the example above is correct because result was private to letters and is unaccessible in writing after the function returns. The following example shows an incorrect use of  assumeUnique.
Bad:
private char[] buffer;
string letters(char first, char last)
{
  if (first >= last) return null; // fine

  auto sneaky = buffer;
  sneaky.length = last - first + 1;
  foreach (i, ref e; sneaky)
  {
    e = 'a' + i;
  }
  return assumeUnique(sneaky); // BAD

}


The example above wreaks havoc on client code because it is modifying arrays that callers considered immutable. To obtain an immutable array from the writable array buffer, replace the last line with:
return to!(string)(sneaky); // not that sneaky anymore



The call will duplicate the array appropriately.

Checking for uniqueness during compilation is possible in certain cases (see the unique and lent keywords in the ArchJava language), but complicates the language considerably. The downside of  assumeUnique's convention-based usage is that at this time there is no formal checking of the correctness of the assumption; on the upside, the idiomatic use of  assumeUnique is simple and rare enough to be tolerable.

pure nothrow @trusted bool  pointsTo(S, T, Tdummy = void)(auto ref const S source, ref const T target) if (__traits(isRef, source) || isDynamicArray!S || isPointer!S || is(S == class));

Returns true if source's representation embeds a pointer that points to target's representation or somewhere inside it.

If source is or contains a dynamic array, then, then  pointsTo will check if there is overlap between the dynamic array and target's representation.

If source is or contains a union, then every member of the union is checked for embedded pointers. This may lead to false positives, depending on which should be considered the "active" member of the union.

If source is a class, then  pointsTo will handle it as a pointer.

If target is a pointer, a dynamic array or a class, then  pointsTo will only check if source points to target, not what target references.

Note:
Evaluating  pointsTo(x, x) checks whether x has internal pointers. This should only be done as an assertive test, as the language is free to assume objects don't have internal pointers (TDPL 7.1.3.5).

class  ErrnoException: object.Exception;

Thrown if errors that set errno occur.


CommonType!(T1, T2)  ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler);
CommonType!(T1, T2)  ifThrown(E : Throwable, T1, T2)(lazy scope T1 expression, scope T2 delegate(E) errorHandler);
CommonType!(T1, T2)  ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler);

ML-style functional exception handling. Runs the supplied expression and returns its result. If the expression throws a Throwable, runs the supplied error handler instead and return its result. The error handler's type must be the same as the expression's type.

Parameters
E The type of Throwables to catch. Defaults to ${D Exception}
T1 The type of the expression.
T2 The return type of the error handler.
T1 expression The expression to run and return its result.
T2 errorHandler The handler to run if the expression throwed.
Examples
//Revert to a default value upon an error:

assert("x".to!int().ifThrown(0) == 0);


You can also chain multiple calls to  ifThrown, each capturing errors from the entire preceding expression.
Example:
//Chaining multiple calls to ifThrown to attempt multiple things in a row:

string s="true";
assert(s.to!int().
        ifThrown(cast(int)s.to!double()).
        ifThrown(cast(int)s.to!bool())
        == 1);

//Respond differently to different types of errors

assert(enforce("x".to!int() < 1).to!string()
        .ifThrown!ConvException("not a number")
        .ifThrown!Exception("number too small")
        == "not a number");


The expression and the errorHandler must have a common type they can both be implicitly casted to, and that type will be the type of the compound expression.
Examples
//null and new Object have a common type(Object).

static assert(is(typeof(null.ifThrown(new Object())) == Object));
static assert(is(typeof((new Object()).ifThrown(null)) == Object));

//1 and new Object do not have a common type.

static assert(!__traits(compiles, 1.ifThrown(new Object())));
static assert(!__traits(compiles, (new Object()).ifThrown(1)));


If you need to use the actual thrown expection, you can use a delegate.
Example:
//Use a lambda to get the thrown object.

assert("%s".format().ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");