1 // Written in the D programming language.
4 This module defines functions related to exceptions and general error
5 handling. It also defines functions intended to aid in unit testing.
7 $(SCRIPT inhibitQuickIndex = 1;)
10 $(TR $(TH Category) $(TH Functions))
11 $(TR $(TD Assumptions) $(TD
12 $(LREF assertNotThrown)
15 $(LREF assumeWontThrow)
18 $(TR $(TD Enforce) $(TD
23 $(TR $(TD Handlers) $(TD
24 $(LREF collectException)
25 $(LREF collectExceptionMsg)
30 $(LREF basicExceptionCtors)
31 $(LREF emptyExceptionMsg)
32 $(LREF ErrnoException)
33 $(LREF RangePrimitive)
37 Copyright: Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-.
38 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0)
39 Authors: $(HTTP erdani.org, Andrei Alexandrescu) and
40 $(HTTP jmdavisprog.com, Jonathan M Davis)
41 Source: $(PHOBOSSRC std/exception.d)
49 import core.stdc.stdlib : malloc, free;
50 import std.algorithm.comparison : equal;
51 import std.algorithm.iteration : map, splitter;
52 import std.algorithm.searching : endsWith;
53 import std.conv : ConvException, to;
54 import std.range : front, retro;
56 // use enforce like assert
58 enforce(a > 2, "a needs to be higher than 2.");
60 // enforce can throw a custom exception
61 enforce!ConvException(a > 2, "a needs to be higher than 2.");
63 // enforce will return it's input
65 auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
66 scope(exit) free(memory.ptr);
68 // collectException can be used to test for exceptions
69 Exception e = collectException("abc".to!int);
70 assert(e.file.endsWith("conv.d"));
72 // and just for the exception message
73 string msg = collectExceptionMsg("abc".to!int);
74 assert(msg == "Unexpected 'a' when converting from type string to type int");
76 // assertThrown can be used to assert that an exception is thrown
77 assertThrown!ConvException("abc".to!int);
79 // ifThrown can be used to provide a default value if an exception is thrown
80 assert("x".to!int().ifThrown(0) == 0);
82 // handle is a more advanced version of ifThrown for ranges
83 auto r = "12,1337z32,54".splitter(',').map!(a => to!int(a));
84 auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
85 assert(h.equal([12, 0, 54]));
86 assertThrown!ConvException(h.retro.equal([54, 0, 12]));
88 // basicExceptionCtors avoids the boilerplate when creating custom exceptions
89 static class MeaCulpa : Exception
91 mixin basicExceptionCtors;
93 e = collectException((){throw new MeaCulpa("diagnostic message");}());
94 assert(e.msg == "diagnostic message");
95 assert(e.file == __FILE__);
96 assert(e.line == __LINE__ - 3);
98 // assumeWontThrow can be used to cast throwing code into `nothrow`
99 void exceptionFreeCode() nothrow
101 // auto-decoding only throws if an invalid UTF char is given
102 assumeWontThrow("abc".front);
105 // assumeUnique can be used to cast mutable instance to an `immutable` one
107 char[] str = " mutable".dup;
109 immutable res = assumeUnique(str);
110 assert(res == "immutable");
113 import std.range.primitives;
117 Asserts that the given expression does $(I not) throw the given type
118 of `Throwable`. If a `Throwable` of the given type is thrown,
119 it is caught and does not escape assertNotThrown. Rather, an
120 `AssertError` is thrown. However, any other `Throwable`s will escape.
123 T = The `Throwable` to test for.
124 expression = The expression to test.
125 msg = Optional message to output on test failure.
126 If msg is empty, and the thrown exception has a
127 non-empty msg field, the exception's msg field
128 will be output on test failure.
129 file = The file where the error occurred.
130 Defaults to `__FILE__`.
131 line = The line where the error occurred.
132 Defaults to `__LINE__`.
135 `AssertError` if the given `Throwable` is thrown.
138 the result of `expression`.
140 auto assertNotThrown(T : Throwable = Exception, E)
143 string file = __FILE__,
144 size_t line = __LINE__)
146 import core.exception : AssertError;
153 immutable message = msg.length == 0 ? t.msg : msg;
154 immutable tail = message.length == 0 ? "." : ": " ~ message;
155 throw new AssertError("assertNotThrown failed: " ~ T.stringof ~ " was thrown" ~ tail, file, line, t);
161 import core.exception : AssertError;
164 assertNotThrown!StringException(enforce!StringException(true, "Error!"));
166 //Exception is the default.
167 assertNotThrown(enforce!StringException(true, "Error!"));
169 assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
170 enforce!StringException(false, "Error!"))) ==
171 `assertNotThrown failed: StringException was thrown: Error!`);
175 import core.exception : AssertError;
177 assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
178 enforce!StringException(false, ""), "Error!")) ==
179 `assertNotThrown failed: StringException was thrown: Error!`);
181 assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
182 enforce!StringException(false, ""))) ==
183 `assertNotThrown failed: StringException was thrown.`);
185 assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
186 enforce!StringException(false, ""), "")) ==
187 `assertNotThrown failed: StringException was thrown.`);
192 import core.exception : AssertError;
194 void throwEx(Throwable t) { throw t; }
195 bool nothrowEx() { return true; }
199 assert(assertNotThrown!Exception(nothrowEx()));
201 catch (AssertError) assert(0);
205 assert(assertNotThrown!Exception(nothrowEx(), "It's a message"));
207 catch (AssertError) assert(0);
211 assert(assertNotThrown!AssertError(nothrowEx()));
213 catch (AssertError) assert(0);
217 assert(assertNotThrown!AssertError(nothrowEx(), "It's a message"));
219 catch (AssertError) assert(0);
225 assertNotThrown!Exception(
226 throwEx(new Exception("It's an Exception")));
228 catch (AssertError) thrown = true;
236 assertNotThrown!Exception(
237 throwEx(new Exception("It's an Exception")), "It's a message");
239 catch (AssertError) thrown = true;
247 assertNotThrown!AssertError(
248 throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)));
250 catch (AssertError) thrown = true;
258 assertNotThrown!AssertError(
259 throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)),
262 catch (AssertError) thrown = true;
268 Asserts that the given expression throws the given type of `Throwable`.
269 The `Throwable` is caught and does not escape assertThrown. However,
270 any other `Throwable`s $(I will) escape, and if no `Throwable`
271 of the given type is thrown, then an `AssertError` is thrown.
274 T = The `Throwable` to test for.
275 expression = The expression to test.
276 msg = Optional message to output on test failure.
277 file = The file where the error occurred.
278 Defaults to `__FILE__`.
279 line = The line where the error occurred.
280 Defaults to `__LINE__`.
283 `AssertError` if the given `Throwable` is not thrown.
285 void assertThrown(T : Throwable = Exception, E)
288 string file = __FILE__,
289 size_t line = __LINE__)
291 import core.exception : AssertError;
297 throw new AssertError("assertThrown failed: No " ~ T.stringof ~ " was thrown"
298 ~ (msg.length == 0 ? "." : ": ") ~ msg,
304 import core.exception : AssertError;
307 assertThrown!StringException(enforce!StringException(false, "Error!"));
309 //Exception is the default.
310 assertThrown(enforce!StringException(false, "Error!"));
312 assert(collectExceptionMsg!AssertError(assertThrown!StringException(
313 enforce!StringException(true, "Error!"))) ==
314 `assertThrown failed: No StringException was thrown.`);
319 import core.exception : AssertError;
321 void throwEx(Throwable t) { throw t; }
326 assertThrown!Exception(throwEx(new Exception("It's an Exception")));
328 catch (AssertError) assert(0);
332 assertThrown!Exception(throwEx(new Exception("It's an Exception")),
335 catch (AssertError) assert(0);
339 assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
340 __FILE__, __LINE__)));
342 catch (AssertError) assert(0);
346 assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
347 __FILE__, __LINE__)),
350 catch (AssertError) assert(0);
356 assertThrown!Exception(nothrowEx());
366 assertThrown!Exception(nothrowEx(), "It's a message");
376 assertThrown!AssertError(nothrowEx());
386 assertThrown!AssertError(nothrowEx(), "It's a message");
396 Enforces that the given value is true.
397 If the given value is false, an exception is thrown.
400 $(LI `msg` - error message as a `string`)
401 $(LI `dg` - custom delegate that return a string and is only called if an exception occurred)
402 $(LI `ex` - custom exception to be thrown. It is `lazy` and is only created if an exception occurred)
406 value = The value to test.
407 E = Exception type to throw if the value evaluates to false.
408 msg = The error message to put in the exception if it is thrown.
409 dg = The delegate to be called if the value evaluates to false.
410 ex = The exception to throw if the value evaluates to false.
411 file = The source file of the caller.
412 line = The line number of the caller.
414 Returns: `value`, if `cast(bool) value` is true. Otherwise,
415 depending on the chosen overload, `new Exception(msg)`, `dg()` or `ex` is thrown.
418 `enforce` is used to throw exceptions and is therefore intended to
419 aid in error handling. It is $(I not) intended for verifying the logic
420 of your program. That is what `assert` is for. Also, do not use
421 `enforce` inside of contracts (i.e. inside of `in` and `out`
422 blocks and `invariant`s), because contracts are compiled out when
423 compiling with $(I -release).
425 If a delegate is passed, the safety and purity of this function are inferred
426 from `Dg`'s safety and purity.
428 template enforce(E : Throwable = Exception)
429 if (is(typeof(new E("", string.init, size_t.init)) : Throwable) ||
430 is(typeof(new E(string.init, size_t.init)) : Throwable))
433 T enforce(T)(T value, lazy const(char)[] msg = null,
434 string file = __FILE__, size_t line = __LINE__)
435 if (is(typeof({ if (!value) {} })))
437 if (!value) bailOut!E(file, line, msg);
443 T enforce(T, Dg, string file = __FILE__, size_t line = __LINE__)
444 (T value, scope Dg dg)
445 if (isSomeFunction!Dg && is(typeof( dg() )) &&
446 is(typeof({ if (!value) {} })))
453 T enforce(T)(T value, lazy Throwable ex)
455 if (!value) throw ex();
462 import core.stdc.stdlib : malloc, free;
463 import std.conv : ConvException, to;
465 // use enforce like assert
467 enforce(a > 2, "a needs to be higher than 2.");
469 // enforce can throw a custom exception
470 enforce!ConvException(a > 2, "a needs to be higher than 2.");
472 // enforce will return it's input
474 auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
475 scope(exit) free(memory.ptr);
481 assertNotThrown(enforce(true, new Exception("this should not be thrown")));
482 assertThrown(enforce(false, new Exception("this should be thrown")));
488 assert(enforce(123) == 123);
492 enforce(false, "error");
497 assert(e.msg == "error");
498 assert(e.file == __FILE__);
499 assert(e.line == __LINE__-7);
503 /// Alias your own enforce function
506 import std.conv : ConvException;
507 alias convEnforce = enforce!ConvException;
508 assertNotThrown(convEnforce(true));
509 assertThrown!ConvException(convEnforce(false, "blah"));
512 private noreturn bailOut(E : Throwable = Exception)(string file, size_t line, scope const(char)[] msg)
514 static if (is(typeof(new E(string.init, string.init, size_t.init))))
516 throw new E(msg ? msg.idup : "Enforcement failed", file, line);
518 else static if (is(typeof(new E(string.init, size_t.init))))
520 throw new E(file, line);
524 static assert(0, "Expected this(string, string, size_t) or this(string, size_t)" ~
525 " constructor for " ~ __traits(identifier, E));
529 // https://issues.dlang.org/show_bug.cgi?id=10510
532 extern(C) void cFoo() { }
533 enforce(false, &cFoo);
536 // purity and safety inference test
539 static foreach (EncloseSafe; [false, true])
540 static foreach (EnclosePure; [false, true])
542 static foreach (BodySafe; [false, true])
543 static foreach (BodyPure; [false, true])
547 (EncloseSafe ? "@safe " : "") ~
548 (EnclosePure ? "pure " : "") ~
549 "{ enforce(true, { " ~
551 (BodySafe ? "" : "auto p = &n + 10; " ) ~ // unsafe code
552 (BodyPure ? "" : "static int g; g = 10; ") ~ // impure code
556 (BodySafe || !EncloseSafe) && (!EnclosePure || BodyPure);
559 pragma(msg, "safe = ", EncloseSafe?1:0, "/", BodySafe?1:0, ", ",
560 "pure = ", EnclosePure?1:0, "/", BodyPure?1:0, ", ",
561 "expect = ", expect?"OK":"NG", ", ",
564 static assert(__traits(compiles, mixin(code)()) == expect);
569 // Test for https://issues.dlang.org/show_bug.cgi?id=8637
575 ~this() {} // impure & unsafe destructor
576 bool opCast(T:bool)() {
577 int* p = cast(int*) 0; // unsafe operation
578 int n = g; // impure operation
586 enforce(s, new Exception(""));
590 alias E1 = Exception;
591 static class E2 : Exception
593 this(string fn, size_t ln) { super("", fn, ln); }
595 static class E3 : Exception
597 this(string msg) { super(msg, __FILE__, __LINE__); }
603 // https://issues.dlang.org/show_bug.cgi?id=14685
608 this() { super("Not found"); }
610 static assert(!__traits(compiles, { enforce!E(false); }));
614 Enforces that the given value is true, throwing an `ErrnoException` if it
618 value = The value to test.
619 msg = The message to include in the `ErrnoException` if it is thrown.
621 Returns: `value`, if `cast(bool) value` is true. Otherwise,
622 $(D new ErrnoException(msg)) is thrown. It is assumed that the last
623 operation set `errno` to an error code corresponding with the failed
626 alias errnoEnforce = enforce!ErrnoException;
631 import core.stdc.stdio : fclose, fgets, fopen;
632 import std.file : thisExePath;
633 import std.string : toStringz;
635 auto f = fopen(thisExePath.toStringz, "r").errnoEnforce;
636 scope(exit) fclose(f);
638 auto line = fgets(buf.ptr, buf.length, f);
639 enforce(line !is null); // expect a non-empty line
643 Catches and returns the exception thrown from the given expression.
644 If no exception is thrown, then null is returned and `result` is
645 set to the result of the expression.
647 Note that while `collectException` $(I can) be used to collect any
648 `Throwable` and not just `Exception`s, it is generally ill-advised to
649 catch anything that is neither an `Exception` nor a type derived from
650 `Exception`. So, do not use `collectException` to collect
651 non-`Exception`s unless you're sure that that's what you really want to
655 T = The type of exception to catch.
656 expression = The expression which may throw an exception.
657 result = The result of the expression if no exception is thrown.
659 T collectException(T = Exception, E)(lazy E expression, ref E result)
663 result = expression();
675 int foo() { throw new Exception("blah"); }
676 assert(collectException(foo(), b));
678 int[] a = new int[3];
679 import core.exception : RangeError;
680 assert(collectException!RangeError(a[4], b));
684 Catches and returns the exception thrown from the given expression.
685 If no exception is thrown, then null is returned. `E` can be
688 Note that while `collectException` $(I can) be used to collect any
689 `Throwable` and not just `Exception`s, it is generally ill-advised to
690 catch anything that is neither an `Exception` nor a type derived from
691 `Exception`. So, do not use `collectException` to collect
692 non-`Exception`s unless you're sure that that's what you really want to
696 T = The type of exception to catch.
697 expression = The expression which may throw an exception.
699 T collectException(T : Throwable = Exception, E)(lazy E expression)
715 int foo() { throw new Exception("blah"); }
716 assert(collectException(foo()).msg == "blah");
720 Catches the exception thrown from the given expression and returns the
721 msg property of that exception. If no exception is thrown, then null is
722 returned. `E` can be `void`.
724 If an exception is thrown but it has an empty message, then
725 `emptyExceptionMsg` is returned.
727 Note that while `collectExceptionMsg` $(I can) be used to collect any
728 `Throwable` and not just `Exception`s, it is generally ill-advised to
729 catch anything that is neither an `Exception` nor a type derived from
730 `Exception`. So, do not use `collectExceptionMsg` to collect
731 non-`Exception`s unless you're sure that that's what you really want to
735 T = The type of exception to catch.
736 expression = The expression which may throw an exception.
738 string collectExceptionMsg(T = Exception, E)(lazy E expression)
740 import std.array : empty;
745 return cast(string) null;
748 return e.msg.empty ? emptyExceptionMsg : e.msg;
753 void throwFunc() { throw new Exception("My Message."); }
754 assert(collectExceptionMsg(throwFunc()) == "My Message.");
756 void nothrowFunc() {}
757 assert(collectExceptionMsg(nothrowFunc()) is null);
759 void throwEmptyFunc() { throw new Exception(""); }
760 assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg);
764 Value that collectExceptionMsg returns when it catches an exception
765 with an empty exception message.
767 enum emptyExceptionMsg = "<Empty Exception Message>";
770 * Casts a mutable array to an immutable array in an idiomatic
771 * manner. Technically, `assumeUnique` just inserts a cast,
772 * but its name documents assumptions on the part of the
773 * caller. `assumeUnique(arr)` should only be called when
774 * there are no more active mutable aliases to elements of $(D
775 * arr). To strengthen this assumption, `assumeUnique(arr)`
776 * also clears `arr` before returning. Essentially $(D
777 * assumeUnique(arr)) indicates commitment from the caller that there
778 * is no more mutable access to any of `arr`'s elements
779 * (transitively), and that all future accesses will be done through
780 * the immutable array returned by `assumeUnique`.
782 * Typically, `assumeUnique` is used to return arrays from
783 * functions that have allocated and built them.
786 * array = The array to cast to immutable.
788 * Returns: The immutable array.
796 * char[] result = new char['z' - 'a' + 1];
797 * foreach (i, ref e; result)
799 * e = cast(char)('a' + i);
801 * return assumeUnique(result);
806 * The use in the example above is correct because `result`
807 * was private to `letters` and is inaccessible in writing
808 * after the function returns. The following example shows an
809 * incorrect use of `assumeUnique`.
815 * private char[] buffer;
816 * string letters(char first, char last)
818 * if (first >= last) return null; // fine
819 * auto sneaky = buffer;
820 * sneaky.length = last - first + 1;
821 * foreach (i, ref e; sneaky)
823 * e = cast(char)('a' + i);
825 * return assumeUnique(sneaky); // BAD
830 * The example above wreaks havoc on client code because it is
831 * modifying arrays that callers considered immutable. To obtain an
832 * immutable array from the writable array `buffer`, replace
833 * the last line with:
836 * return to!(string)(sneaky); // not that sneaky anymore
839 * The call will duplicate the array appropriately.
841 * Note that checking for uniqueness during compilation is
842 * possible in certain cases, especially when a function is
843 * marked as a pure function. The following example does not
844 * need to call assumeUnique because the compiler can infer the
845 * uniqueness of the array in the pure function:
849 * string letters() pure
851 * char[] result = new char['z' - 'a' + 1];
852 * foreach (i, ref e; result)
854 * e = cast(char)('a' + i);
861 * For more on infering uniqueness see the $(B unique) and
862 * $(B lent) keywords in the
863 * $(HTTP www.cs.cmu.edu/~aldrich/papers/aldrich-dissertation.pdf, ArchJava)
866 * The downside of using `assumeUnique`'s
867 * convention-based usage is that at this time there is no
868 * formal checking of the correctness of the assumption;
869 * on the upside, the idiomatic use of `assumeUnique` is
870 * simple and rare enough to be tolerable.
873 immutable(T)[] assumeUnique(T)(T[] array) pure nothrow
875 return .assumeUnique(array); // call ref version
878 immutable(T)[] assumeUnique(T)(ref T[] array) pure nothrow
880 auto result = cast(immutable(T)[]) array;
885 immutable(T[U]) assumeUnique(T, U)(ref T[U] array) pure nothrow
887 auto result = cast(immutable(T[U])) array;
895 int[] arr = new int[1];
896 auto arr1 = arr.assumeUnique;
897 static assert(is(typeof(arr1) == immutable(int)[]));
905 int[string] arr = ["a":1];
906 auto arr1 = arr.assumeUnique;
907 static assert(is(typeof(arr1) == immutable(int[string])));
909 assert(arr1.keys == ["a"]);
913 * Wraps a possibly-throwing expression in a `nothrow` wrapper so that it
914 * can be called by a `nothrow` function.
916 * This wrapper function documents commitment on the part of the caller that
917 * the appropriate steps have been taken to avoid whatever conditions may
918 * trigger an exception during the evaluation of `expr`. If it turns out
919 * that the expression $(I does) throw at runtime, the wrapper will throw an
922 * (Note that `Throwable` objects such as `AssertError` that do not
923 * subclass `Exception` may be thrown even from `nothrow` functions,
924 * since they are considered to be serious runtime problems that cannot be
928 * expr = The expression asserted not to throw.
929 * msg = The message to include in the `AssertError` if the assumption turns
931 * file = The source file name of the caller.
932 * line = The line number of the caller.
935 * The value of `expr`, if any.
937 T assumeWontThrow(T)(lazy T expr,
939 string file = __FILE__,
940 size_t line = __LINE__) nothrow
942 import core.exception : AssertError;
949 import std.range.primitives : empty;
950 immutable tail = msg.empty ? "." : ": " ~ msg;
951 throw new AssertError("assumeWontThrow failed: Expression did throw" ~
959 import std.math.algebraic : sqrt;
961 // This function may throw.
962 int squareRoot(int x)
965 throw new Exception("Tried to take root of negative number");
966 return cast(int) sqrt(cast(double) x);
969 // This function never throws.
970 int computeLength(int x, int y) nothrow
972 // Since x*x + y*y is always positive, we can safely assume squareRoot
973 // won't throw, and use it to implement this nothrow function. If it
974 // does throw (e.g., if x*x + y*y overflows a 32-bit value), then the
975 // program will terminate.
976 return assumeWontThrow(squareRoot(x*x + y*y));
979 assert(computeLength(3, 4) == 5);
984 import core.exception : AssertError;
988 throw new Exception("I threw up");
992 assumeWontThrow(alwaysThrows());
994 assertThrown!AssertError(bad());
998 Checks whether a given source object contains pointers or references to a given
1002 source = The source object
1003 target = The target object
1006 The function is explicitly annotated `@nogc` because inference could fail,
1007 see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, issue 17084).
1009 Returns: `true` if `source`'s representation embeds a pointer
1010 that points to `target`'s representation or somewhere inside
1013 If `source` is or contains a dynamic array, then, then these functions will check
1014 if there is overlap between the dynamic array and `target`'s representation.
1016 If `source` is a class, then it will be handled as a pointer.
1018 If `target` is a pointer, a dynamic array or a class, then these functions will only
1019 check if `source` points to `target`, $(I not) what `target` references.
1021 If `source` is or contains a union or `void[n]`, then there may be either false positives or
1024 `doesPointTo` will return `true` if it is absolutely certain
1025 `source` points to `target`. It may produce false negatives, but never
1026 false positives. This function should be prefered when trying to validate
1029 `mayPointTo` will return `false` if it is absolutely certain
1030 `source` does not point to `target`. It may produce false positives, but never
1031 false negatives. This function should be prefered for defensively choosing a
1034 Note: Evaluating $(D doesPointTo(x, x)) checks whether `x` has
1035 internal pointers. This should only be done as an assertive test,
1036 as the language is free to assume objects don't have internal pointers
1039 bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow
1040 if (__traits(isRef, source) || isDynamicArray!S ||
1041 isPointer!S || is(S == class))
1043 static if (isPointer!S || is(S == class) || is(S == interface))
1045 const m = *cast(void**) &source;
1046 const b = cast(void*) ⌖
1047 const e = b + target.sizeof;
1048 return b <= m && m < e;
1050 else static if (is(S == struct) || is(S == union))
1052 foreach (i, Subobj; typeof(source.tupleof))
1053 static if (!isUnionAliased!(S, i))
1054 if (doesPointTo(source.tupleof[i], target)) return true;
1057 else static if (isStaticArray!S)
1059 static if (!is(S == void[n], size_t n))
1061 foreach (ref s; source)
1062 if (doesPointTo(s, target)) return true;
1066 else static if (isDynamicArray!S)
1068 import std.array : overlap;
1069 return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0;
1077 // for shared objects
1079 bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow
1081 return doesPointTo!(shared S, shared T, void)(source, target);
1085 bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow
1086 if (__traits(isRef, source) || isDynamicArray!S ||
1087 isPointer!S || is(S == class))
1089 static if (isPointer!S || is(S == class) || is(S == interface))
1091 const m = *cast(void**) &source;
1092 const b = cast(void*) ⌖
1093 const e = b + target.sizeof;
1094 return b <= m && m < e;
1096 else static if (is(S == struct) || is(S == union))
1098 foreach (i, Subobj; typeof(source.tupleof))
1099 if (mayPointTo(source.tupleof[i], target)) return true;
1102 else static if (isStaticArray!S)
1104 static if (is(S == void[n], size_t n))
1106 static if (n >= (void[]).sizeof)
1108 // could contain a slice, which could point at anything.
1109 // But a void[N] that is all 0 cannot point anywhere
1110 import std.algorithm.searching : any;
1111 if (__ctfe || any(cast(ubyte[]) source[]))
1114 else static if (n >= (void*).sizeof)
1116 // Reinterpreting cast is impossible during ctfe
1120 // Only check for properly aligned pointers
1121 enum al = (void*).alignof - 1;
1122 const base = cast(size_t) &source;
1123 const alBase = (base + al) & ~al;
1125 if ((n - (alBase - base)) >= (void*).sizeof &&
1126 mayPointTo(*(cast(void**) alBase), target))
1132 foreach (size_t i; 0 .. S.length)
1133 if (mayPointTo(source[i], target)) return true;
1138 else static if (isDynamicArray!S)
1140 import std.array : overlap;
1141 return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0;
1149 // for shared objects
1151 bool mayPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow
1153 return mayPointTo!(shared S, shared T, void)(source, target);
1161 assert(!p.doesPointTo(i));
1163 assert( p.doesPointTo(i));
1166 /// Structs and Unions
1177 // structs and unions "own" their members
1178 // pointsTo will answer true if one of the members pointsTo.
1179 assert(!s.doesPointTo(s.v)); //s.v is just v member of s, so not pointed.
1180 assert( s.p.doesPointTo(i)); //i is pointed by s.p.
1181 assert( s .doesPointTo(i)); //which means i is pointed by s itself.
1183 // Unions will behave exactly the same. Points to will check each "member"
1184 // individually, even if they share the same memory
1187 /// Arrays (dynamic and static)
1191 // trick the compiler when initializing slice
1192 // https://issues.dlang.org/show_bug.cgi?id=18637
1194 int[] slice = [0, 1, 2, 3, 4];
1195 int[5] arr = [0, 1, 2, 3, 4];
1196 int*[] slicep = [p];
1197 int*[1] arrp = [&i];
1199 // A slice points to all of its members:
1200 assert( slice.doesPointTo(slice[3]));
1201 assert(!slice[0 .. 2].doesPointTo(slice[3])); // Object 3 is outside of the
1204 // Note that a slice will not take into account what its members point to.
1205 assert( slicep[0].doesPointTo(i));
1206 assert(!slicep .doesPointTo(i));
1208 // static arrays are objects that own their members, just like structs:
1209 assert(!arr.doesPointTo(arr[0])); // arr[0] is just a member of arr, so not
1211 assert( arrp[0].doesPointTo(i)); // i is pointed by arrp[0].
1212 assert( arrp .doesPointTo(i)); // which means i is pointed by arrp
1215 // Notice the difference between static and dynamic arrays:
1216 assert(!arr .doesPointTo(arr[0]));
1217 assert( arr[].doesPointTo(arr[0]));
1218 assert( arrp .doesPointTo(i));
1219 assert(!arrp[].doesPointTo(i));
1227 this(int* p){this.p = p;}
1234 // Classes are a bit particular, as they are treated like simple pointers
1235 // to a class payload.
1236 assert( a.p.doesPointTo(i)); // a.p points to i.
1237 assert(!a .doesPointTo(i)); // Yet a itself does not point i.
1239 //To check the class payload itself, iterate on its members:
1242 import std.traits : Fields;
1244 foreach (index, _; Fields!C)
1245 if (doesPointTo(a.tupleof[index], i))
1250 // To check if a class points a specific payload, a direct memmory check
1252 auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a;
1253 assert(b.doesPointTo(*aLoc)); // b points to where a is pointing
1257 version (StdUnittest)
1259 // https://issues.dlang.org/show_bug.cgi?id=17084
1260 // the bug doesn't happen if these declarations are in the unittest block
1262 private struct Page17084
1265 int opCmp(P)(P) { return 0; }
1266 int opCmp(P)(shared(P)) shared { return 0; }
1269 private struct URL17084
1272 string toString()() const { return ""; }
1273 alias toString this;
1277 // https://issues.dlang.org/show_bug.cgi?id=17084
1280 import std.algorithm.sorting : sort;
1283 shared(Page17084)[] p;
1289 struct S1 { int a; S1 * b; }
1292 assert(doesPointTo(p, a1));
1296 assert(doesPointTo(a2, a1));
1298 struct S3 { int[10] a; }
1300 auto a4 = a3.a[2 .. 3];
1301 assert(doesPointTo(a4, a3));
1303 auto a5 = new double[4];
1304 auto a6 = a5[1 .. 2];
1305 assert(!doesPointTo(a5, a6));
1307 auto a7 = new double[3];
1308 auto a8 = new double[][1];
1310 assert(!doesPointTo(a8[0], a8[0]));
1312 // don't invoke postblit on subobjects
1314 static struct NoCopy { this(this) { assert(0); } }
1315 static struct Holder { NoCopy a, b, c; }
1317 cast(void) doesPointTo(h, h);
1321 shared sh3sub = sh3.a[];
1322 assert(doesPointTo(sh3sub, sh3));
1324 int[] darr = [1, 2, 3, 4];
1326 //dynamic arrays don't point to each other, or slices of themselves
1327 assert(!doesPointTo(darr, darr));
1328 assert(!doesPointTo(darr[0 .. 1], darr));
1330 //But they do point their elements
1332 assert(doesPointTo(darr, darr[i]));
1333 assert(doesPointTo(darr[0 .. 3], darr[2]));
1334 assert(!doesPointTo(darr[0 .. 3], darr[3]));
1339 //tests with static arrays
1340 //Static arrays themselves are just objects, and don't really *point* to anything.
1341 //They aggregate their contents, much the same way a structure aggregates its attributes.
1342 //*However* The elements inside the static array may themselves point to stuff.
1346 assert(!doesPointTo(k, k)); //an array doesn't point to itself
1347 //Technically, k doesn't point its elements, although it does alias them
1348 assert(!doesPointTo(k, k[0]));
1349 assert(!doesPointTo(k, k[1]));
1350 //But an extracted slice will point to the same array.
1351 assert(doesPointTo(k[], k));
1352 assert(doesPointTo(k[], k[1]));
1354 //An array of pointers
1359 assert( doesPointTo(pp, a)); //The array contains a pointer to a
1360 assert(!doesPointTo(pp, b)); //The array does NOT contain a pointer to b
1361 assert(!doesPointTo(pp, pp)); //The array does not point itslef
1363 //A struct containing a static array of pointers
1370 assert( doesPointTo(s, a)); //The struct contains an array that points a
1371 assert(!doesPointTo(s, b)); //But doesn't point b
1372 assert(!doesPointTo(s, s)); //The struct doesn't actually point itslef.
1374 //An array containing structs that have pointers
1379 SS[2] ss = [SS(&a), SS(null)];
1380 assert( doesPointTo(ss, a)); //The array contains a struct that points to a
1381 assert(!doesPointTo(ss, b)); //The array doesn't contains a struct that points to b
1382 assert(!doesPointTo(ss, ss)); //The array doesn't point itself.
1384 // https://issues.dlang.org/show_bug.cgi?id=20426
1385 align((void*).alignof) void[32] voidArr = void;
1386 (cast(void*[]) voidArr[])[] = null; // Ensure no false pointers
1388 // zeroed void ranges can't point at anything
1389 assert(!mayPointTo(voidArr, a));
1390 assert(!mayPointTo(voidArr, b));
1392 *cast(void**) &voidArr[16] = &a; // Pointers should be found
1394 alias SA = void[size_t.sizeof + 3];
1395 SA *smallArr1 = cast(SA*)&voidArr;
1396 SA *smallArr2 = cast(SA*)&(voidArr[16]);
1398 // But it should only consider properly aligned pointers
1399 // Write single bytes to avoid issues due to misaligned writes
1400 void*[1] tmp = [&b];
1401 (cast(ubyte[]) voidArr[3 .. 3 + (void*).sizeof])[] = cast(ubyte[]) tmp[];
1404 assert( mayPointTo(*smallArr2, a));
1405 assert(!mayPointTo(*smallArr1, b));
1407 assert(!doesPointTo(voidArr, a)); // Value might be a false pointer
1408 assert(!doesPointTo(voidArr, b));
1410 SA *smallArr3 = cast(SA *) &voidArr[13]; // Works for weird sizes/alignments
1411 assert( mayPointTo(*smallArr3, a));
1412 assert(!mayPointTo(*smallArr3, b));
1414 assert(!doesPointTo(*smallArr3, a));
1415 assert(!doesPointTo(*smallArr3, b));
1417 auto v3 = cast(void[3]*) &voidArr[16]; // Arrays smaller than pointers are ignored
1418 assert(!mayPointTo(*v3, a));
1419 assert(!mayPointTo(*v3, b));
1421 assert(!doesPointTo(*v3, a));
1422 assert(!doesPointTo(*v3, b));
1424 assert(mayPointTo(voidArr, a)); // slice-contiaining void[N] might point at anything
1425 assert(mayPointTo(voidArr, b));
1428 void[16] arr1 = void;
1429 void[size_t.sizeof] arr2 = void;
1431 return mayPointTo(arr1, var) && !doesPointTo(arr1, var) &&
1432 mayPointTo(arr2, var) && !doesPointTo(arr2, var);
1437 @system unittest //Unions
1440 union U //Named union
1447 union //Anonymous union
1456 assert(!doesPointTo(u, i));
1457 assert(!doesPointTo(s, i));
1458 assert(!mayPointTo(u, i));
1459 assert(!mayPointTo(s, i));
1463 assert(!doesPointTo(u, i));
1464 assert(!doesPointTo(s, i));
1465 assert( mayPointTo(u, i));
1466 assert( mayPointTo(s, i));
1468 u.asInt = cast(size_t)&i;
1469 s.asInt = cast(size_t)&i;
1470 assert(!doesPointTo(u, i));
1471 assert(!doesPointTo(s, i));
1472 assert( mayPointTo(u, i));
1473 assert( mayPointTo(s, i));
1476 @system unittest //Classes
1484 assert(!doesPointTo(a, b)); //a does not point to b
1486 assert(!doesPointTo(a, i)); //a does not point to i
1488 @safe unittest //alias this test
1495 @property int* foo(){return &i;}
1498 assert(is(S : int*));
1500 assert(!doesPointTo(s, i));
1501 assert( doesPointTo(s, j));
1502 assert( doesPointTo(cast(int*) s, i));
1503 assert(!doesPointTo(cast(int*) s, j));
1505 @safe unittest //more alias this opCast
1510 void* opCast(T)() if (is(T == void*))
1514 alias foo = opCast!(void*);
1517 assert(!doesPointTo(A.init, p));
1518 assert(!mayPointTo(A.init, p));
1522 Returns true if the field at index `i` in ($D T) shares its address with another field.
1524 Note: This does not merelly check if the field is a member of an union, but also that
1525 it is not a single child.
1527 package enum isUnionAliased(T, size_t i) = isUnionAliasedImpl!T(T.tupleof[i].offsetof);
1528 private bool isUnionAliasedImpl(T)(size_t offset)
1531 foreach (i, U; typeof(T.tupleof))
1532 if (T.tupleof[i].offsetof == offset)
1541 int a0; //Not aliased
1544 int a1; //Not aliased
1553 int b0; //Not aliased
1564 static assert(!isUnionAliased!(S, 0)); //a0;
1565 static assert(!isUnionAliased!(S, 1)); //a1;
1566 static assert( isUnionAliased!(S, 2)); //a2;
1567 static assert( isUnionAliased!(S, 3)); //a3;
1568 static assert(!isUnionAliased!(S, 4)); //a4;
1569 static assert(!isUnionAliased!(S.A4, 0)); //a4.b0;
1570 static assert(!isUnionAliased!(S, 5)); //a5;
1571 static assert( isUnionAliased!(S.A5, 0)); //a5.b0;
1572 static assert( isUnionAliased!(S.A5, 1)); //a5.b1;
1575 version (CRuntime_Glibc) version = GNU_STRERROR;
1576 version (CRuntime_UClibc) version = GNU_STRERROR;
1578 package string errnoString(int errno) nothrow @trusted
1580 import core.stdc.string : strlen;
1581 version (GNU_STRERROR)
1583 import core.stdc.string : strerror_r;
1584 char[1024] buf = void;
1585 auto s = strerror_r(errno, buf.ptr, buf.length);
1587 else version (Posix)
1590 import core.stdc.string : strerror_r;
1591 char[1024] buf = void;
1593 if (strerror_r(errno, buf.ptr, buf.length) == 0)
1596 return "Unknown error";
1600 import core.stdc.string : strerror;
1601 auto s = strerror(errno);
1603 return s[0 .. s.strlen].idup;
1606 /*********************
1607 * Thrown if errors that set `errno` occur.
1609 class ErrnoException : Exception
1611 /// Operating system error code.
1612 final @property uint errno() nothrow pure @nogc @safe { return _errno; }
1613 private uint _errno;
1614 /// Constructor which takes an error message. The current global $(REF errno, core,stdc,errno) value is used as error code.
1615 this(string msg, string file = null, size_t line = 0) @safe
1617 import core.stdc.errno : errno;
1618 this(msg, errno, file, line);
1620 /// Constructor which takes an error message and error code.
1621 this(string msg, int errno, string file = null, size_t line = 0) @safe
1624 super(msg ~ " (" ~ errnoString(errno) ~ ")", file, line);
1631 import core.stdc.errno : EAGAIN;
1632 auto ex = new ErrnoException("oh no", EAGAIN);
1633 assert(ex.errno == EAGAIN);
1636 /// errno is used by default if no explicit error code is provided
1639 import core.stdc.errno : errno, EAGAIN;
1642 scope(exit) errno = old;
1644 // fake that errno got set by the callee
1646 auto ex = new ErrnoException("oh no");
1647 assert(ex.errno == EAGAIN);
1651 ML-style functional exception handling. Runs the supplied expression and
1652 returns its result. If the expression throws a `Throwable`, runs the
1653 supplied error handler instead and return its result. The error handler's
1654 type must be the same as the expression's type.
1657 E = The type of `Throwable`s to catch. Defaults to `Exception`
1658 T1 = The type of the expression.
1659 T2 = The return type of the error handler.
1660 expression = The expression to run and return its result.
1661 errorHandler = The handler to run if the expression throwed.
1664 expression, if it does not throw. Otherwise, returns the result of
1668 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler)
1670 static assert(!is(typeof(return) == void),
1671 "The error handler's return value("
1673 ") does not have a common type with the expression("
1679 return expression();
1683 return errorHandler();
1689 CommonType!(T1, T2) ifThrown(E : Throwable, T1, T2)(lazy scope T1 expression, scope T2 delegate(E) errorHandler)
1691 static assert(!is(typeof(return) == void),
1692 "The error handler's return value("
1694 ") does not have a common type with the expression("
1700 return expression();
1704 return errorHandler(e);
1709 //delegate version, general overload to catch any Exception
1710 CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler)
1712 static assert(!is(typeof(return) == void),
1713 "The error handler's return value("
1715 ") does not have a common type with the expression("
1721 return expression();
1725 return errorHandler(e);
1729 /// Revert to a default value upon an error:
1732 import std.conv : to;
1733 assert("x".to!int.ifThrown(0) == 0);
1737 Chain multiple calls to ifThrown, each capturing errors from the
1738 entire preceding expression.
1742 import std.conv : ConvException, to;
1744 assert(s.to!int.ifThrown(cast(int) s.to!double)
1745 .ifThrown(cast(int) s.to!bool) == 1);
1748 assert(s.to!int.ifThrown(cast(int) s.to!double)
1749 .ifThrown(cast(int) s.to!bool) == 2);
1751 // Respond differently to different types of errors
1752 alias orFallback = (lazy a) => a.ifThrown!ConvException("not a number")
1753 .ifThrown!Exception("number too small");
1755 assert(orFallback(enforce("x".to!int < 1).to!string) == "not a number");
1756 assert(orFallback(enforce("2".to!int < 1).to!string) == "number too small");
1760 The expression and the errorHandler must have a common type they can both
1761 be implicitly casted to, and that type will be the type of the compound
1766 // null and new Object have a common type(Object).
1767 static assert(is(typeof(null.ifThrown(new Object())) == Object));
1768 static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1770 // 1 and new Object do not have a common type.
1771 static assert(!__traits(compiles, 1.ifThrown(new Object())));
1772 static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1775 /// Use a lambda to get the thrown object.
1778 import std.format : format;
1779 assert("%s".format.ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
1787 //Revert to a default value upon an error:
1788 assert("x".to!int().ifThrown(0) == 0);
1790 //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1793 ifThrown(cast(int) s.to!double()).
1794 ifThrown(cast(int) s.to!bool())
1797 //Respond differently to different types of errors
1798 assert(enforce("x".to!int() < 1).to!string()
1799 .ifThrown!ConvException("not a number")
1800 .ifThrown!Exception("number too small")
1803 //null and new Object have a common type(Object).
1804 static assert(is(typeof(null.ifThrown(new Object())) == Object));
1805 static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1807 //1 and new Object do not have a common type.
1808 static assert(!__traits(compiles, 1.ifThrown(new Object())));
1809 static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1811 //Use a lambda to get the thrown object.
1812 assert("%s".format().ifThrown(e => e.classinfo.name) == "std.format.FormatException");
1817 import core.exception;
1820 //Basic behaviour - all versions.
1821 assert("1".to!int().ifThrown(0) == 1);
1822 assert("x".to!int().ifThrown(0) == 0);
1823 assert("1".to!int().ifThrown!ConvException(0) == 1);
1824 assert("x".to!int().ifThrown!ConvException(0) == 0);
1825 assert("1".to!int().ifThrown(e=>0) == 1);
1826 assert("x".to!int().ifThrown(e=>0) == 0);
1827 static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1829 assert("1".to!int().ifThrown!ConvException(e=>0) == 1);
1830 assert("x".to!int().ifThrown!ConvException(e=>0) == 0);
1833 //Exceptions other than stated not caught.
1834 assert("x".to!int().ifThrown!StringException(0).collectException!ConvException() !is null);
1835 static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1837 assert("x".to!int().ifThrown!StringException(e=>0).collectException!ConvException() !is null);
1840 //Default does not include errors.
1841 int throwRangeError() { throw new RangeError; }
1842 assert(throwRangeError().ifThrown(0).collectException!RangeError() !is null);
1843 assert(throwRangeError().ifThrown(e=>0).collectException!RangeError() !is null);
1845 //Incompatible types are not accepted.
1846 static assert(!__traits(compiles, 1.ifThrown(new Object())));
1847 static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1848 static assert(!__traits(compiles, 1.ifThrown(e=>new Object())));
1849 static assert(!__traits(compiles, (new Object()).ifThrown(e=>1)));
1852 version (StdUnittest) package
1853 void assertCTFEable(alias dg)()
1855 static assert({ cast(void) dg(); return true; }());
1859 /** This `enum` is used to select the primitives of the range to handle by the
1860 $(LREF handle) range wrapper. The values of the `enum` can be `OR`'d to
1861 select multiple primitives to be handled.
1863 `RangePrimitive.access` is a shortcut for the access primitives; `front`,
1864 `back` and `opIndex`.
1866 `RangePrimitive.pop` is a shortcut for the mutating primitives;
1867 `popFront` and `popBack`.
1871 front = 0b00_0000_0001, ///
1872 back = 0b00_0000_0010, /// Ditto
1873 popFront = 0b00_0000_0100, /// Ditto
1874 popBack = 0b00_0000_1000, /// Ditto
1875 empty = 0b00_0001_0000, /// Ditto
1876 save = 0b00_0010_0000, /// Ditto
1877 length = 0b00_0100_0000, /// Ditto
1878 opDollar = 0b00_1000_0000, /// Ditto
1879 opIndex = 0b01_0000_0000, /// Ditto
1880 opSlice = 0b10_0000_0000, /// Ditto
1881 access = front | back | opIndex, /// Ditto
1882 pop = popFront | popBack, /// Ditto
1888 import std.algorithm.comparison : equal;
1889 import std.algorithm.iteration : map, splitter;
1890 import std.conv : to, ConvException;
1892 auto s = "12,1337z32,54,2,7,9,1z,6,8";
1894 // The next line composition will throw when iterated
1895 // as some elements of the input do not convert to integer
1896 auto r = s.splitter(',').map!(a => to!int(a));
1898 // Substitute 0 for cases of ConvException
1899 auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
1900 assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
1906 import std.algorithm.comparison : equal;
1907 import std.range : retro;
1908 import std.utf : UTFException;
1910 auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
1912 auto handled = str.handle!(UTFException, RangePrimitive.access,
1913 (e, r) => ' '); // Replace invalid code points with spaces
1915 assert(handled.equal("hello world")); // `front` is handled,
1916 assert(handled.retro.equal("dlrow olleh")); // as well as `back`
1919 /** Handle exceptions thrown from range primitives.
1921 Use the $(LREF RangePrimitive) enum to specify which primitives to _handle.
1922 Multiple range primitives can be handled at once by using the `OR` operator
1923 or the pseudo-primitives `RangePrimitive.access` and `RangePrimitive.pop`.
1924 All handled primitives must have return types or values compatible with the
1925 user-supplied handler.
1928 E = The type of `Throwable` to _handle.
1929 primitivesToHandle = Set of range primitives to _handle.
1930 handler = The callable that is called when a handled primitive throws a
1931 `Throwable` of type `E`. The handler must accept arguments of
1932 the form $(D E, ref IRange) and its return value is used as the primitive's
1933 return value whenever `E` is thrown. For `opIndex`, the handler can
1934 optionally recieve a third argument; the index that caused the exception.
1935 input = The range to _handle.
1937 Returns: A wrapper `struct` that preserves the range interface of `input`.
1940 Infinite ranges with slicing support must return an instance of
1941 $(REF Take, std,range) when sliced with a specific lower and upper
1942 bound (see $(REF hasSlicing, std,range,primitives)); `handle` deals with
1943 this by `take`ing 0 from the return value of the handler function and
1944 returning that when an exception is caught.
1946 auto handle(E : Throwable, RangePrimitive primitivesToHandle, alias handler, Range)(Range input)
1947 if (isInputRange!Range)
1949 static struct Handler
1951 private Range range;
1953 static if (isForwardRange!Range)
1955 @property typeof(this) save()
1957 static if (primitivesToHandle & RangePrimitive.save)
1961 return typeof(this)(range.save);
1965 return typeof(this)(handler(exception, this.range));
1969 return typeof(this)(range.save);
1973 static if (isInfinite!Range)
1975 enum bool empty = false;
1979 @property bool empty()
1981 static if (primitivesToHandle & RangePrimitive.empty)
1985 return this.range.empty;
1989 return handler(exception, this.range);
1993 return this.range.empty;
1997 @property auto ref front()
1999 static if (primitivesToHandle & RangePrimitive.front)
2003 return this.range.front;
2007 return handler(exception, this.range);
2011 return this.range.front;
2016 static if (primitivesToHandle & RangePrimitive.popFront)
2020 this.range.popFront();
2024 handler(exception, this.range);
2028 this.range.popFront();
2031 static if (isBidirectionalRange!Range)
2033 @property auto ref back()
2035 static if (primitivesToHandle & RangePrimitive.back)
2039 return this.range.back;
2043 return handler(exception, this.range);
2047 return this.range.back;
2052 static if (primitivesToHandle & RangePrimitive.popBack)
2056 this.range.popBack();
2060 handler(exception, this.range);
2064 this.range.popBack();
2068 static if (isRandomAccessRange!Range)
2070 auto ref opIndex(size_t index)
2072 static if (primitivesToHandle & RangePrimitive.opIndex)
2076 return this.range[index];
2080 static if (__traits(compiles, handler(exception, this.range, index)))
2081 return handler(exception, this.range, index);
2083 return handler(exception, this.range);
2087 return this.range[index];
2091 static if (hasLength!Range)
2093 @property auto length()
2095 static if (primitivesToHandle & RangePrimitive.length)
2099 return this.range.length;
2103 return handler(exception, this.range);
2107 return this.range.length;
2111 static if (hasSlicing!Range)
2113 static if (hasLength!Range)
2115 typeof(this) opSlice(size_t lower, size_t upper)
2117 static if (primitivesToHandle & RangePrimitive.opSlice)
2121 return typeof(this)(this.range[lower .. upper]);
2125 return typeof(this)(handler(exception, this.range));
2129 return typeof(this)(this.range[lower .. upper]);
2132 else static if (is(typeof(Range.init[size_t.init .. $])))
2134 import std.range : Take, takeExactly;
2135 static struct DollarToken {}
2136 enum opDollar = DollarToken.init;
2138 typeof(this) opSlice(size_t lower, DollarToken)
2140 static if (primitivesToHandle & RangePrimitive.opSlice)
2144 return typeof(this)(this.range[lower .. $]);
2148 return typeof(this)(handler(exception, this.range));
2152 return typeof(this)(this.range[lower .. $]);
2155 Take!Handler opSlice(size_t lower, size_t upper)
2157 static if (primitivesToHandle & RangePrimitive.opSlice)
2161 return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2165 return takeExactly(typeof(this)(handler(exception, this.range)), 0);
2169 return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2175 return Handler(input);
2181 import std.algorithm.comparison : equal;
2182 import std.algorithm.iteration : map, splitter;
2183 import std.conv : to, ConvException;
2185 auto s = "12,1337z32,54,2,7,9,1z,6,8";
2187 // The next line composition will throw when iterated
2188 // as some elements of the input do not convert to integer
2189 auto r = s.splitter(',').map!(a => to!int(a));
2191 // Substitute 0 for cases of ConvException
2192 auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
2193 assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
2199 import std.algorithm.comparison : equal;
2200 import std.range : retro;
2201 import std.utf : UTFException;
2203 auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
2205 auto handled = str.handle!(UTFException, RangePrimitive.access,
2206 (e, r) => ' '); // Replace invalid code points with spaces
2208 assert(handled.equal("hello world")); // `front` is handled,
2209 assert(handled.retro.equal("dlrow olleh")); // as well as `back`
2212 pure nothrow @safe unittest
2214 static struct ThrowingRange
2217 @property bool empty()
2219 throw new Exception("empty has thrown");
2222 @property int front()
2224 throw new Exception("front has thrown");
2227 @property int back()
2229 throw new Exception("back has thrown");
2234 throw new Exception("popFront has thrown");
2239 throw new Exception("popBack has thrown");
2244 throw new Exception("opIndex has thrown");
2247 ThrowingRange opSlice(size_t, size_t)
2249 throw new Exception("opSlice has thrown");
2252 @property size_t length()
2254 throw new Exception("length has thrown");
2257 alias opDollar = length;
2259 @property ThrowingRange save()
2261 throw new Exception("save has thrown");
2265 static assert(isInputRange!ThrowingRange);
2266 static assert(isForwardRange!ThrowingRange);
2267 static assert(isBidirectionalRange!ThrowingRange);
2268 static assert(hasSlicing!ThrowingRange);
2269 static assert(hasLength!ThrowingRange);
2271 auto f = ThrowingRange();
2272 auto fb = f.handle!(Exception, RangePrimitive.front | RangePrimitive.back,
2274 assert(fb.front == -1);
2275 assert(fb.back == -1);
2276 assertThrown(fb.popFront());
2277 assertThrown(fb.popBack());
2278 assertThrown(fb.empty);
2279 assertThrown(fb.save);
2280 assertThrown(fb[0]);
2282 auto accessRange = f.handle!(Exception, RangePrimitive.access,
2284 assert(accessRange.front == -1);
2285 assert(accessRange.back == -1);
2286 assert(accessRange[0] == -1);
2287 assertThrown(accessRange.popFront());
2288 assertThrown(accessRange.popBack());
2290 auto pfb = f.handle!(Exception, RangePrimitive.pop, (e, r) => -1)();
2292 pfb.popFront(); // this would throw otherwise
2293 pfb.popBack(); // this would throw otherwise
2295 auto em = f.handle!(Exception,
2296 RangePrimitive.empty, (e, r) => false)();
2300 auto arr = f.handle!(Exception,
2301 RangePrimitive.opIndex, (e, r) => 1337)();
2303 assert(arr[0] == 1337);
2305 auto arr2 = f.handle!(Exception,
2306 RangePrimitive.opIndex, (e, r, i) => i)();
2308 assert(arr2[0] == 0);
2309 assert(arr2[1337] == 1337);
2311 auto save = f.handle!(Exception,
2312 RangePrimitive.save,
2313 function(Exception e, ref ThrowingRange r) {
2314 return ThrowingRange();
2319 auto slice = f.handle!(Exception,
2320 RangePrimitive.opSlice, (e, r) => ThrowingRange())();
2322 auto sliced = slice[0 .. 1337]; // this would throw otherwise
2324 static struct Infinite
2326 import std.range : Take;
2328 enum bool empty = false;
2329 int front() { assert(false); }
2330 void popFront() { assert(false); }
2331 Infinite save() @property { assert(false); }
2332 static struct DollarToken {}
2333 enum opDollar = DollarToken.init;
2334 Take!Infinite opSlice(size_t, size_t) { assert(false); }
2335 Infinite opSlice(size_t, DollarToken)
2337 throw new Exception("opSlice has thrown");
2341 static assert(isInputRange!Infinite);
2342 static assert(isInfinite!Infinite);
2343 static assert(hasSlicing!Infinite);
2345 assertThrown(Infinite()[0 .. $]);
2347 auto infinite = Infinite.init.handle!(Exception,
2348 RangePrimitive.opSlice, (e, r) => Infinite())();
2350 auto infSlice = infinite[0 .. $]; // this would throw otherwise
2355 Convenience mixin for trivially sub-classing exceptions
2357 Even trivially sub-classing an exception involves writing boilerplate code
2358 for the constructor to: 1$(RPAREN) correctly pass in the source file and line number
2359 the exception was thrown from; 2$(RPAREN) be usable with $(LREF enforce) which
2360 expects exception constructors to take arguments in a fixed order. This
2361 mixin provides that boilerplate code.
2363 Note however that you need to mark the $(B mixin) line with at least a
2364 minimal (i.e. just $(B ///)) DDoc comment if you want the mixed-in
2365 constructors to be documented in the newly created Exception subclass.
2367 $(RED Current limitation): Due to
2368 $(LINK2 https://issues.dlang.org/show_bug.cgi?id=11500, bug #11500),
2369 currently the constructors specified in this mixin cannot be overloaded with
2370 any other custom constructors. Thus this mixin can currently only be used
2371 when no such custom constructors need to be explicitly specified.
2373 mixin template basicExceptionCtors()
2377 msg = The message for the exception.
2378 file = The file where the exception occurred.
2379 line = The line number where the exception occurred.
2380 next = The previous exception in the chain of exceptions, if any.
2382 this(string msg, string file = __FILE__, size_t line = __LINE__,
2383 Throwable next = null) @nogc @safe pure nothrow
2385 super(msg, file, line, next);
2390 msg = The message for the exception.
2391 next = The previous exception in the chain of exceptions.
2392 file = The file where the exception occurred.
2393 line = The line number where the exception occurred.
2395 this(string msg, Throwable next, string file = __FILE__,
2396 size_t line = __LINE__) @nogc @safe pure nothrow
2398 super(msg, file, line, next);
2405 class MeaCulpa: Exception
2408 mixin basicExceptionCtors;
2412 throw new MeaCulpa("test");
2415 assert(e.msg == "test");
2416 assert(e.file == __FILE__);
2417 assert(e.line == __LINE__ - 5);
2421 @safe pure nothrow unittest
2423 class TestException : Exception { mixin basicExceptionCtors; }
2424 auto e = new Exception("msg");
2425 auto te1 = new TestException("foo");
2426 auto te2 = new TestException("foo", e);
2431 class TestException : Exception { mixin basicExceptionCtors; }
2432 auto e = new Exception("!!!");
2434 auto te1 = new TestException("message", "file", 42, e);
2435 assert(te1.msg == "message");
2436 assert(te1.file == "file");
2437 assert(te1.line == 42);
2438 assert(te1.next is e);
2440 auto te2 = new TestException("message", e, "file", 42);
2441 assert(te2.msg == "message");
2442 assert(te2.file == "file");
2443 assert(te2.line == 42);
2444 assert(te2.next is e);
2446 auto te3 = new TestException("foo");
2447 assert(te3.msg == "foo");
2448 assert(te3.file == __FILE__);
2449 assert(te3.line == __LINE__ - 3);
2450 assert(te3.next is null);
2452 auto te4 = new TestException("foo", e);
2453 assert(te4.msg == "foo");
2454 assert(te4.file == __FILE__);
2455 assert(te4.line == __LINE__ - 3);
2456 assert(te4.next is e);