c++: auto in trailing-return-type in parameter [PR117778]
[gcc.git] / libphobos / src / std / exception.d
blob9b1a7c8a62cedbd7c9835bd4be15b2114f615157
1 // Written in the D programming language.
3 /++
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;)
8 $(DIVC quickindex,
9 $(BOOKTABLE,
10 $(TR $(TH Category) $(TH Functions))
11 $(TR $(TD Assumptions) $(TD
12 $(LREF assertNotThrown)
13 $(LREF assertThrown)
14 $(LREF assumeUnique)
15 $(LREF assumeWontThrow)
16 $(LREF mayPointTo)
18 $(TR $(TD Enforce) $(TD
19 $(LREF doesPointTo)
20 $(LREF enforce)
21 $(LREF errnoEnforce)
23 $(TR $(TD Handlers) $(TD
24 $(LREF collectException)
25 $(LREF collectExceptionMsg)
26 $(LREF ifThrown)
27 $(LREF handle)
29 $(TR $(TD Other) $(TD
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)
44 module std.exception;
46 /// Synopis
47 @system unittest
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
57 int a = 3;
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
64 enum size = 42;
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
106 // use with care
107 char[] str = " mutable".dup;
108 str[0 .. 2] = "im";
109 immutable res = assumeUnique(str);
110 assert(res == "immutable");
113 import std.range.primitives;
114 import std.traits;
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.
122 Params:
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__`.
134 Throws:
135 `AssertError` if the given `Throwable` is thrown.
137 Returns:
138 the result of `expression`.
140 auto assertNotThrown(T : Throwable = Exception, E)
141 (lazy E expression,
142 string msg = null,
143 string file = __FILE__,
144 size_t line = __LINE__)
146 import core.exception : AssertError;
149 return expression();
151 catch (T t)
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);
159 @system unittest
161 import core.exception : AssertError;
163 import std.string;
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!`);
173 @system unittest
175 import core.exception : AssertError;
176 import std.string;
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.`);
190 @system unittest
192 import core.exception : AssertError;
194 static noreturn 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);
222 bool thrown = false;
225 assertNotThrown!Exception(
226 throwEx(new Exception("It's an Exception")));
228 catch (AssertError) thrown = true;
229 assert(thrown);
233 bool thrown = false;
236 assertNotThrown!Exception(
237 throwEx(new Exception("It's an Exception")), "It's a message");
239 catch (AssertError) thrown = true;
240 assert(thrown);
244 bool thrown = false;
247 assertNotThrown!AssertError(
248 throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)));
250 catch (AssertError) thrown = true;
251 assert(thrown);
255 bool thrown = false;
258 assertNotThrown!AssertError(
259 throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)),
260 "It's a message");
262 catch (AssertError) thrown = true;
263 assert(thrown);
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.
273 Params:
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__`.
282 Throws:
283 `AssertError` if the given `Throwable` is not thrown.
285 void assertThrown(T : Throwable = Exception, E)
286 (lazy E expression,
287 string msg = null,
288 string file = __FILE__,
289 size_t line = __LINE__)
291 import core.exception : AssertError;
294 expression();
295 catch (T)
296 return;
298 static if (!is(immutable E == immutable noreturn))
299 throw new AssertError("assertThrown failed: No " ~ T.stringof ~ " was thrown"
300 ~ (msg.length == 0 ? "." : ": ") ~ msg,
301 file, line);
304 @system unittest
306 import core.exception : AssertError;
307 import std.string;
309 assertThrown!StringException(enforce!StringException(false, "Error!"));
311 //Exception is the default.
312 assertThrown(enforce!StringException(false, "Error!"));
314 assert(collectExceptionMsg!AssertError(assertThrown!StringException(
315 enforce!StringException(true, "Error!"))) ==
316 `assertThrown failed: No StringException was thrown.`);
319 @system unittest
321 import core.exception : AssertError;
323 static noreturn throwEx(Throwable t) { throw t; }
324 void nothrowEx() { }
328 assertThrown!Exception(throwEx(new Exception("It's an Exception")));
330 catch (AssertError) assert(0);
334 assertThrown!Exception(throwEx(new Exception("It's an Exception")),
335 "It's a message");
337 catch (AssertError) assert(0);
341 assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
342 __FILE__, __LINE__)));
344 catch (AssertError) assert(0);
348 assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
349 __FILE__, __LINE__)),
350 "It's a message");
352 catch (AssertError) assert(0);
356 bool thrown = false;
358 assertThrown!Exception(nothrowEx());
359 catch (AssertError)
360 thrown = true;
362 assert(thrown);
366 bool thrown = false;
368 assertThrown!Exception(nothrowEx(), "It's a message");
369 catch (AssertError)
370 thrown = true;
372 assert(thrown);
376 bool thrown = false;
378 assertThrown!AssertError(nothrowEx());
379 catch (AssertError)
380 thrown = true;
382 assert(thrown);
386 bool thrown = false;
388 assertThrown!AssertError(nothrowEx(), "It's a message");
389 catch (AssertError)
390 thrown = true;
392 assert(thrown);
398 Enforces that the given value is true.
399 If the given value is false, an exception is thrown.
401 $(UL
402 $(LI `msg` - error message as a `string`)
403 $(LI `dg` - custom delegate that return a string and is only called if an exception occurred)
404 $(LI `ex` - custom exception to be thrown. It is `lazy` and is only created if an exception occurred)
407 Params:
408 value = The value to test.
409 E = Exception type to throw if the value evaluates to false.
410 msg = The error message to put in the exception if it is thrown.
411 dg = The delegate to be called if the value evaluates to false.
412 ex = The exception to throw if the value evaluates to false.
413 file = The source file of the caller.
414 line = The line number of the caller.
416 Returns: `value`, if `cast(bool) value` is true. Otherwise,
417 depending on the chosen overload, `new Exception(msg)`, `dg()` or `ex` is thrown.
419 $(PANEL
420 $(NOTE `enforce` is used to throw exceptions and is therefore intended to
421 aid in error handling. It is $(I not) intended for verifying the logic
422 of your program - that is what `assert` is for.)
424 Do not use
425 `enforce` inside of contracts (i.e. inside of `in` and `out`
426 blocks and `invariant`s), because contracts are compiled out when
427 compiling with $(I -release).
430 If a delegate is passed, the safety and purity of this function are inferred
431 from `Dg`'s safety and purity.
433 template enforce(E : Throwable = Exception)
434 if (is(typeof(new E("", string.init, size_t.init)) : Throwable) ||
435 is(typeof(new E(string.init, size_t.init)) : Throwable))
438 T enforce(T)(T value, lazy const(char)[] msg = null,
439 string file = __FILE__, size_t line = __LINE__)
440 if (is(typeof({ if (!value) {} })))
442 if (!value) bailOut!E(file, line, msg);
443 return value;
447 /// ditto
448 T enforce(T, Dg, string file = __FILE__, size_t line = __LINE__)
449 (T value, scope Dg dg)
450 if (isSomeFunction!Dg && is(typeof( dg() )) &&
451 is(typeof({ if (!value) {} })))
453 if (!value) dg();
454 return value;
457 /// ditto
458 T enforce(T)(T value, lazy Throwable ex)
460 if (!value) throw ex();
461 return value;
465 @system unittest
467 import core.stdc.stdlib : malloc, free;
468 import std.conv : ConvException, to;
470 // use enforce like assert
471 int a = 3;
472 enforce(a > 2, "a needs to be higher than 2.");
474 // enforce can throw a custom exception
475 enforce!ConvException(a > 2, "a needs to be higher than 2.");
477 // enforce will return it's input
478 enum size = 42;
479 auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
480 scope(exit) free(memory.ptr);
484 @safe unittest
486 assertNotThrown(enforce(true, new Exception("this should not be thrown")));
487 assertThrown(enforce(false, new Exception("this should be thrown")));
491 @safe unittest
493 assert(enforce(123) == 123);
497 enforce(false, "error");
498 assert(false);
500 catch (Exception e)
502 assert(e.msg == "error");
503 assert(e.file == __FILE__);
504 assert(e.line == __LINE__-7);
508 /// Alias your own enforce function
509 @safe unittest
511 import std.conv : ConvException;
512 alias convEnforce = enforce!ConvException;
513 assertNotThrown(convEnforce(true));
514 assertThrown!ConvException(convEnforce(false, "blah"));
517 private noreturn bailOut(E : Throwable = Exception)(string file, size_t line, scope const(char)[] msg)
519 static if (is(typeof(new E(string.init, string.init, size_t.init))))
521 throw new E(msg ? msg.idup : "Enforcement failed", file, line);
523 else static if (is(typeof(new E(string.init, size_t.init))))
525 throw new E(file, line);
527 else
529 static assert(0, "Expected this(string, string, size_t) or this(string, size_t)" ~
530 " constructor for " ~ __traits(identifier, E));
534 // https://issues.dlang.org/show_bug.cgi?id=10510
535 @safe unittest
537 extern(C) void cFoo() { }
538 enforce(false, &cFoo);
541 // purity and safety inference test
542 @system unittest
544 static foreach (EncloseSafe; [false, true])
545 static foreach (EnclosePure; [false, true])
547 static foreach (BodySafe; [false, true])
548 static foreach (BodyPure; [false, true])
550 enum code =
551 "delegate void() " ~
552 (EncloseSafe ? "@safe " : "") ~
553 (EnclosePure ? "pure " : "") ~
554 "{ enforce(true, { " ~
555 "int n; " ~
556 (BodySafe ? "" : "auto p = &n + 10; " ) ~ // unsafe code
557 (BodyPure ? "" : "static int g; g = 10; ") ~ // impure code
558 "}); " ~
559 "}";
560 enum expect =
561 (BodySafe || !EncloseSafe) && (!EnclosePure || BodyPure);
563 version (none)
564 pragma(msg, "safe = ", EncloseSafe?1:0, "/", BodySafe?1:0, ", ",
565 "pure = ", EnclosePure?1:0, "/", BodyPure?1:0, ", ",
566 "expect = ", expect?"OK":"NG", ", ",
567 "code = ", code);
569 static assert(__traits(compiles, mixin(code)()) == expect);
574 // Test for https://issues.dlang.org/show_bug.cgi?id=8637
575 @system unittest
577 struct S
579 static int g;
580 ~this() {} // impure & unsafe destructor
581 bool opCast(T:bool)() {
582 int* p = cast(int*) 0; // unsafe operation
583 int n = g; // impure operation
584 return true;
587 S s;
589 enforce(s);
590 enforce(s, {});
591 enforce(s, new Exception(""));
593 errnoEnforce(s);
595 alias E1 = Exception;
596 static class E2 : Exception
598 this(string fn, size_t ln) { super("", fn, ln); }
600 static class E3 : Exception
602 this(string msg) { super(msg, __FILE__, __LINE__); }
604 enforce!E1(s);
605 enforce!E2(s);
608 // https://issues.dlang.org/show_bug.cgi?id=14685
609 @safe unittest
611 class E : Exception
613 this() { super("Not found"); }
615 static assert(!__traits(compiles, { enforce!E(false); }));
619 Enforces that the given value is true, throwing an `ErrnoException` if it
620 is not.
622 Params:
623 value = The value to test.
624 msg = The message to include in the `ErrnoException` if it is thrown.
626 Returns: `value`, if `cast(bool) value` is true. Otherwise,
627 $(D new ErrnoException(msg)) is thrown. It is assumed that the last
628 operation set `errno` to an error code corresponding with the failed
629 condition.
631 alias errnoEnforce = enforce!ErrnoException;
634 @system unittest
636 import core.stdc.stdio : fclose, fgets, fopen;
637 import std.file : thisExePath;
638 import std.string : toStringz;
640 auto f = fopen(thisExePath.toStringz, "r").errnoEnforce;
641 scope(exit) fclose(f);
642 char[100] buf;
643 auto line = fgets(buf.ptr, buf.length, f);
644 enforce(line !is null); // expect a non-empty line
648 Catches and returns the exception thrown from the given expression.
649 If no exception is thrown, then null is returned and `result` is
650 set to the result of the expression.
652 Note that while `collectException` $(I can) be used to collect any
653 `Throwable` and not just `Exception`s, it is generally ill-advised to
654 catch anything that is neither an `Exception` nor a type derived from
655 `Exception`. So, do not use `collectException` to collect
656 non-`Exception`s unless you're sure that that's what you really want to
659 Params:
660 T = The type of exception to catch.
661 expression = The expression which may throw an exception.
662 result = The result of the expression if no exception is thrown.
664 T collectException(T = Exception, E)(lazy E expression, ref E result)
668 result = expression();
670 catch (T e)
672 return e;
674 // Avoid "statement not reachable" warning
675 static if (!is(immutable E == immutable noreturn))
676 return null;
679 @system unittest
681 int b;
682 int foo() { throw new Exception("blah"); }
683 assert(collectException(foo(), b));
685 version (D_NoBoundsChecks) {}
686 else
688 // check for out of bounds error
689 int[] a = new int[3];
690 import core.exception : RangeError;
691 assert(collectException!RangeError(a[4], b));
696 Catches and returns the exception thrown from the given expression.
697 If no exception is thrown, then null is returned. `E` can be
698 `void`.
700 Note that while `collectException` $(I can) be used to collect any
701 `Throwable` and not just `Exception`s, it is generally ill-advised to
702 catch anything that is neither an `Exception` nor a type derived from
703 `Exception`. So, do not use `collectException` to collect
704 non-`Exception`s unless you're sure that that's what you really want to
707 Params:
708 T = The type of exception to catch.
709 expression = The expression which may throw an exception.
711 T collectException(T : Throwable = Exception, E)(lazy E expression)
715 expression();
717 catch (T t)
719 return t;
721 // Avoid "statement not reachable" warning
722 static if (!is(immutable E == immutable noreturn))
723 return null;
727 @safe unittest
729 int foo() { throw new Exception("blah"); }
730 assert(collectException(foo()).msg == "blah");
734 Catches the exception thrown from the given expression and returns the
735 msg property of that exception. If no exception is thrown, then null is
736 returned. `E` can be `void`.
738 If an exception is thrown but it has an empty message, then
739 `emptyExceptionMsg` is returned.
741 Note that while `collectExceptionMsg` $(I can) be used to collect any
742 `Throwable` and not just `Exception`s, it is generally ill-advised to
743 catch anything that is neither an `Exception` nor a type derived from
744 `Exception`. So, do not use `collectExceptionMsg` to collect
745 non-`Exception`s unless you're sure that that's what you really want to
748 Params:
749 T = The type of exception to catch.
750 expression = The expression which may throw an exception.
752 string collectExceptionMsg(T = Exception, E)(lazy E expression)
754 import std.array : empty;
757 expression();
759 // Avoid "statement not reachable" warning
760 static if (!is(immutable E == immutable noreturn))
761 return cast(string) null;
763 catch (T e)
764 return e.msg.empty ? emptyExceptionMsg : e.msg;
767 @safe unittest
769 void throwFunc() { throw new Exception("My Message."); }
770 assert(collectExceptionMsg(throwFunc()) == "My Message.");
772 void nothrowFunc() {}
773 assert(collectExceptionMsg(nothrowFunc()) is null);
775 void throwEmptyFunc() { throw new Exception(""); }
776 assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg);
780 Value that collectExceptionMsg returns when it catches an exception
781 with an empty exception message.
783 enum emptyExceptionMsg = "<Empty Exception Message>";
785 // https://issues.dlang.org/show_bug.cgi?id=22364
786 @system unittest
788 static noreturn foo() { throw new Exception(""); }
790 const ex = collectException!(Exception, noreturn)(foo());
791 assert(ex);
793 const msg = collectExceptionMsg!(Exception, noreturn)(foo());
794 assert(msg);
796 noreturn n;
798 // Triggers a backend assertion failure
799 // collectException!(Exception, noreturn)(foo(), n);
801 static assert(__traits(compiles, collectException!(Exception, noreturn)(foo(), n)));
805 Casts a mutable array to an immutable array in an idiomatic
806 manner. Technically, `assumeUnique` just inserts a cast,
807 but its name documents assumptions on the part of the
808 caller. `assumeUnique(arr)` should only be called when
809 there are no more active mutable aliases to elements of $(D
810 arr). To strengthen this assumption, `assumeUnique(arr)`
811 also clears `arr` before returning. Essentially $(D
812 assumeUnique(arr)) indicates commitment from the caller that there
813 is no more mutable access to any of `arr`'s elements
814 (transitively), and that all future accesses will be done through
815 the immutable array returned by `assumeUnique`.
817 Typically, `assumeUnique` is used to return arrays from
818 functions that have allocated and built them.
820 Params:
821 array = The array to cast to immutable.
823 Returns: The immutable array.
825 Example:
827 $(RUNNABLE_EXAMPLE
828 ----
829 string letters()
831 char[] result = new char['z' - 'a' + 1];
832 foreach (i, ref e; result)
834 e = cast(char)('a' + i);
836 return assumeUnique(result);
838 ----
841 The use in the example above is correct because `result`
842 was private to `letters` and the memory it referenced can no longer be written to
843 after the function returns. The following example shows an
844 incorrect use of `assumeUnique`.
846 Bad:
848 $(RUNNABLE_EXAMPLE
849 ----
850 char[] buffer;
851 string letters(char first, char last)
853 if (first >= last) return null; // fine
854 auto sneaky = buffer;
855 sneaky.length = last - first + 1;
856 foreach (i, ref e; sneaky)
858 e = cast(char)('a' + i);
860 return assumeUnique(sneaky); // BAD
862 ----
865 The example above wreaks havoc on client code because it modifies the
866 returned array that the previous caller considered immutable. To obtain an
867 immutable array from the writable array `buffer`, replace
868 the last line with:
870 ----
871 return to!(string)(sneaky); // not that sneaky anymore
872 ----
874 The `to` call will duplicate the array appropriately.
876 $(PANEL
877 $(NOTE Checking for uniqueness during compilation is
878 possible in certain cases, especially when a function is
879 marked (or inferred) as `pure`. The following example does not
880 need to call `assumeUnique` because the compiler can infer the
881 uniqueness of the array in the pure function:)
883 $(RUNNABLE_EXAMPLE
884 ----
885 static string letters() pure
887 char[] result = new char['z' - 'a' + 1];
888 foreach (i, ref e; result)
890 e = cast(char)('a' + i);
892 return result;
894 ----
897 For more on infering uniqueness see the $(B unique) and
898 $(B lent) keywords in the
899 $(HTTP www.cs.cmu.edu/~aldrich/papers/aldrich-dissertation.pdf, ArchJava)
900 language.
903 The downside of using `assumeUnique`'s
904 convention-based usage is that at this time there is no
905 formal checking of the correctness of the assumption;
906 on the upside, the idiomatic use of `assumeUnique` is
907 simple and rare enough to be tolerable.
909 immutable(T)[] assumeUnique(T)(T[] array) pure nothrow
911 return .assumeUnique(array); // call ref version
913 /// ditto
914 immutable(T)[] assumeUnique(T)(ref T[] array) pure nothrow
916 auto result = cast(immutable(T)[]) array;
917 array = null;
918 return result;
920 /// ditto
921 immutable(T[U]) assumeUnique(T, U)(ref T[U] array) pure nothrow
923 auto result = cast(immutable(T[U])) array;
924 array = null;
925 return result;
929 @system unittest
931 int[] arr = new int[1];
932 auto arr1 = arr.assumeUnique;
933 static assert(is(typeof(arr1) == immutable(int)[]));
934 assert(arr == null);
935 assert(arr1 == [0]);
939 @system unittest
941 int[string] arr = ["a":1];
942 auto arr1 = arr.assumeUnique;
943 static assert(is(typeof(arr1) == immutable(int[string])));
944 assert(arr == null);
945 assert(arr1.keys == ["a"]);
949 * Wraps a possibly-throwing expression in a `nothrow` wrapper so that it
950 * can be called by a `nothrow` function.
952 * This wrapper function documents commitment on the part of the caller that
953 * the appropriate steps have been taken to avoid whatever conditions may
954 * trigger an exception during the evaluation of `expr`. If it turns out
955 * that the expression $(I does) throw at runtime, the wrapper will throw an
956 * `AssertError`.
958 * (Note that `Throwable` objects such as `AssertError` that do not
959 * subclass `Exception` may be thrown even from `nothrow` functions,
960 * since they are considered to be serious runtime problems that cannot be
961 * recovered from.)
963 * Params:
964 * expr = The expression asserted not to throw.
965 * msg = The message to include in the `AssertError` if the assumption turns
966 * out to be false.
967 * file = The source file name of the caller.
968 * line = The line number of the caller.
970 * Returns:
971 * The value of `expr`, if any.
973 T assumeWontThrow(T)(lazy T expr,
974 string msg = null,
975 string file = __FILE__,
976 size_t line = __LINE__) nothrow
978 import core.exception : AssertError;
981 return expr;
983 catch (Exception e)
985 import std.range.primitives : empty;
986 immutable tail = msg.empty ? "." : ": " ~ msg;
987 throw new AssertError("assumeWontThrow failed: Expression did throw" ~
988 tail, file, line);
993 @safe unittest
995 import std.math.algebraic : sqrt;
997 // This function may throw.
998 int squareRoot(int x)
1000 if (x < 0)
1001 throw new Exception("Tried to take root of negative number");
1002 return cast(int) sqrt(cast(double) x);
1005 // This function never throws.
1006 int computeLength(int x, int y) nothrow
1008 // Since x*x + y*y is always positive, we can safely assume squareRoot
1009 // won't throw, and use it to implement this nothrow function. If it
1010 // does throw (e.g., if x*x + y*y overflows a 32-bit value), then the
1011 // program will terminate.
1012 return assumeWontThrow(squareRoot(x*x + y*y));
1015 assert(computeLength(3, 4) == 5);
1018 @system unittest
1020 import core.exception : AssertError;
1022 void alwaysThrows()
1024 throw new Exception("I threw up");
1026 void bad() nothrow
1028 assumeWontThrow(alwaysThrows());
1030 assertThrown!AssertError(bad());
1034 Checks whether a given source object contains pointers or references to a given
1035 target object.
1037 Params:
1038 source = The source object
1039 target = The target object
1041 Bugs:
1042 The function is explicitly annotated `@nogc` because inference could fail,
1043 see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, Bugzilla issue 17084).
1045 Returns: `true` if `source`'s representation embeds a pointer
1046 that points to `target`'s representation or somewhere inside
1049 If `source` is or contains a dynamic array, then, then these functions will check
1050 if there is overlap between the dynamic array and `target`'s representation.
1052 If `source` is a class, then it will be handled as a pointer.
1054 If `target` is a pointer, a dynamic array or a class, then these functions will only
1055 check if `source` points to `target`, $(I not) what `target` references.
1057 If `source` is or contains a union or `void[n]`, then there may be either false positives or
1058 false negatives:
1060 `doesPointTo` will return `true` if it is absolutely certain
1061 `source` points to `target`. It may produce false negatives, but never
1062 false positives. This function should be prefered when trying to validate
1063 input data.
1065 `mayPointTo` will return `false` if it is absolutely certain
1066 `source` does not point to `target`. It may produce false positives, but never
1067 false negatives. This function should be prefered for defensively choosing a
1068 code path.
1070 Note: Evaluating $(D doesPointTo(x, x)) checks whether `x` has
1071 internal pointers. This should only be done as an assertive test,
1072 as the language is free to assume objects don't have internal pointers
1073 (TDPL 7.1.3.5).
1075 bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow
1076 if (__traits(isRef, source) || isDynamicArray!S ||
1077 is(S == U*, U) || is(S == class))
1079 static if (is(S == U*, U) || is(S == class) || is(S == interface))
1081 const m = *cast(void**) &source;
1082 const b = cast(void*) &target;
1083 const e = b + target.sizeof;
1084 return b <= m && m < e;
1086 else static if (is(S == struct) || is(S == union))
1088 foreach (i, Subobj; typeof(source.tupleof))
1089 static if (!isUnionAliased!(S, i))
1090 if (doesPointTo(source.tupleof[i], target)) return true;
1091 return false;
1093 else static if (isStaticArray!S)
1095 static if (!is(S == void[n], size_t n))
1097 foreach (ref s; source)
1098 if (doesPointTo(s, target)) return true;
1100 return false;
1102 else static if (isDynamicArray!S)
1104 import std.array : overlap;
1105 return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0;
1107 else
1109 return false;
1113 // for shared objects
1114 /// ditto
1115 bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow
1117 return doesPointTo!(shared S, shared T, void)(source, target);
1120 /// ditto
1121 bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow
1122 if (__traits(isRef, source) || isDynamicArray!S ||
1123 is(S == U*, U) || is(S == class))
1125 static if (is(S == U*, U) || is(S == class) || is(S == interface))
1127 const m = *cast(void**) &source;
1128 const b = cast(void*) &target;
1129 const e = b + target.sizeof;
1130 return b <= m && m < e;
1132 else static if (is(S == struct) || is(S == union))
1134 foreach (i, Subobj; typeof(source.tupleof))
1135 if (mayPointTo(source.tupleof[i], target)) return true;
1136 return false;
1138 else static if (isStaticArray!S)
1140 static if (is(S == void[n], size_t n))
1142 static if (n >= (void[]).sizeof)
1144 // could contain a slice, which could point at anything.
1145 // But a void[N] that is all 0 cannot point anywhere
1146 import std.algorithm.searching : any;
1147 if (__ctfe || any(cast(ubyte[]) source[]))
1148 return true;
1150 else static if (n >= (void*).sizeof)
1152 // Reinterpreting cast is impossible during ctfe
1153 if (__ctfe)
1154 return true;
1156 // Only check for properly aligned pointers
1157 enum al = (void*).alignof - 1;
1158 const base = cast(size_t) &source;
1159 const alBase = (base + al) & ~al;
1161 if ((n - (alBase - base)) >= (void*).sizeof &&
1162 mayPointTo(*(cast(void**) alBase), target))
1163 return true;
1166 else
1168 foreach (size_t i; 0 .. S.length)
1169 if (mayPointTo(source[i], target)) return true;
1172 return false;
1174 else static if (isDynamicArray!S)
1176 import std.array : overlap;
1177 return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0;
1179 else
1181 return false;
1185 // for shared objects
1186 /// ditto
1187 bool mayPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow
1189 return mayPointTo!(shared S, shared T, void)(source, target);
1192 /// Pointers
1193 @system unittest
1195 int i = 0;
1196 int* p = null;
1197 assert(!p.doesPointTo(i));
1198 p = &i;
1199 assert( p.doesPointTo(i));
1202 /// Structs and Unions
1203 @system unittest
1205 struct S
1207 int v;
1208 int* p;
1210 int i;
1211 auto s = S(0, &i);
1213 // structs and unions "own" their members
1214 // pointsTo will answer true if one of the members pointsTo.
1215 assert(!s.doesPointTo(s.v)); //s.v is just v member of s, so not pointed.
1216 assert( s.p.doesPointTo(i)); //i is pointed by s.p.
1217 assert( s .doesPointTo(i)); //which means i is pointed by s itself.
1219 // Unions will behave exactly the same. Points to will check each "member"
1220 // individually, even if they share the same memory
1223 /// Arrays (dynamic and static)
1224 @system unittest
1226 int i;
1227 // trick the compiler when initializing slice
1228 // https://issues.dlang.org/show_bug.cgi?id=18637
1229 int* p = &i;
1230 int[] slice = [0, 1, 2, 3, 4];
1231 int[5] arr = [0, 1, 2, 3, 4];
1232 int*[] slicep = [p];
1233 int*[1] arrp = [&i];
1235 // A slice points to all of its members:
1236 assert( slice.doesPointTo(slice[3]));
1237 assert(!slice[0 .. 2].doesPointTo(slice[3])); // Object 3 is outside of the
1238 // slice [0 .. 2]
1240 // Note that a slice will not take into account what its members point to.
1241 assert( slicep[0].doesPointTo(i));
1242 assert(!slicep .doesPointTo(i));
1244 // static arrays are objects that own their members, just like structs:
1245 assert(!arr.doesPointTo(arr[0])); // arr[0] is just a member of arr, so not
1246 // pointed.
1247 assert( arrp[0].doesPointTo(i)); // i is pointed by arrp[0].
1248 assert( arrp .doesPointTo(i)); // which means i is pointed by arrp
1249 // itself.
1251 // Notice the difference between static and dynamic arrays:
1252 assert(!arr .doesPointTo(arr[0]));
1253 assert( arr[].doesPointTo(arr[0]));
1254 assert( arrp .doesPointTo(i));
1255 assert(!arrp[].doesPointTo(i));
1258 /// Classes
1259 @system unittest
1261 class C
1263 this(int* p){this.p = p;}
1264 int* p;
1266 int i;
1267 C a = new C(&i);
1268 C b = a;
1270 // Classes are a bit particular, as they are treated like simple pointers
1271 // to a class payload.
1272 assert( a.p.doesPointTo(i)); // a.p points to i.
1273 assert(!a .doesPointTo(i)); // Yet a itself does not point i.
1275 //To check the class payload itself, iterate on its members:
1278 import std.traits : Fields;
1280 foreach (index, _; Fields!C)
1281 if (doesPointTo(a.tupleof[index], i))
1282 return;
1283 assert(0);
1284 }();
1286 // To check if a class points a specific payload, a direct memmory check
1287 // can be done:
1288 auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a;
1289 assert(b.doesPointTo(*aLoc)); // b points to where a is pointing
1293 version (StdUnittest)
1295 // https://issues.dlang.org/show_bug.cgi?id=17084
1296 // the bug doesn't happen if these declarations are in the unittest block
1297 // (static or not).
1298 private struct Page17084
1300 URL17084 url;
1301 int opCmp(P)(P) { return 0; }
1302 int opCmp(P)(shared(P)) shared { return 0; }
1305 private struct URL17084
1307 int[] queryParams;
1308 string toString()() const { return ""; }
1309 alias toString this;
1313 // https://issues.dlang.org/show_bug.cgi?id=17084
1314 @system unittest
1316 import std.algorithm.sorting : sort;
1317 Page17084[] s;
1318 sort(s);
1319 shared(Page17084)[] p;
1320 sort(p);
1323 @system unittest
1325 struct S1 { int a; S1 * b; }
1326 S1 a1;
1327 S1 * p = &a1;
1328 assert(doesPointTo(p, a1));
1330 S1 a2;
1331 a2.b = &a1;
1332 assert(doesPointTo(a2, a1));
1334 struct S3 { int[10] a; }
1335 S3 a3;
1336 auto a4 = a3.a[2 .. 3];
1337 assert(doesPointTo(a4, a3));
1339 auto a5 = new double[4];
1340 auto a6 = a5[1 .. 2];
1341 assert(!doesPointTo(a5, a6));
1343 auto a7 = new double[3];
1344 auto a8 = new double[][1];
1345 a8[0] = a7;
1346 assert(!doesPointTo(a8[0], a8[0]));
1348 // don't invoke postblit on subobjects
1350 static struct NoCopy { this(this) { assert(0); } }
1351 static struct Holder { NoCopy a, b, c; }
1352 Holder h;
1353 cast(void) doesPointTo(h, h);
1356 shared S3 sh3;
1357 shared sh3sub = sh3.a[];
1358 assert(doesPointTo(sh3sub, sh3));
1360 int[] darr = [1, 2, 3, 4];
1362 //dynamic arrays don't point to each other, or slices of themselves
1363 assert(!doesPointTo(darr, darr));
1364 assert(!doesPointTo(darr[0 .. 1], darr));
1366 //But they do point their elements
1367 foreach (i; 0 .. 4)
1368 assert(doesPointTo(darr, darr[i]));
1369 assert(doesPointTo(darr[0 .. 3], darr[2]));
1370 assert(!doesPointTo(darr[0 .. 3], darr[3]));
1373 @system unittest
1375 //tests with static arrays
1376 //Static arrays themselves are just objects, and don't really *point* to anything.
1377 //They aggregate their contents, much the same way a structure aggregates its attributes.
1378 //*However* The elements inside the static array may themselves point to stuff.
1380 //Standard array
1381 int[2] k;
1382 assert(!doesPointTo(k, k)); //an array doesn't point to itself
1383 //Technically, k doesn't point its elements, although it does alias them
1384 assert(!doesPointTo(k, k[0]));
1385 assert(!doesPointTo(k, k[1]));
1386 //But an extracted slice will point to the same array.
1387 assert(doesPointTo(k[], k));
1388 assert(doesPointTo(k[], k[1]));
1390 //An array of pointers
1391 int*[2] pp;
1392 int a;
1393 int b;
1394 pp[0] = &a;
1395 assert( doesPointTo(pp, a)); //The array contains a pointer to a
1396 assert(!doesPointTo(pp, b)); //The array does NOT contain a pointer to b
1397 assert(!doesPointTo(pp, pp)); //The array does not point itslef
1399 //A struct containing a static array of pointers
1400 static struct S
1402 int*[2] p;
1404 S s;
1405 s.p[0] = &a;
1406 assert( doesPointTo(s, a)); //The struct contains an array that points a
1407 assert(!doesPointTo(s, b)); //But doesn't point b
1408 assert(!doesPointTo(s, s)); //The struct doesn't actually point itslef.
1410 //An array containing structs that have pointers
1411 static struct SS
1413 int* p;
1415 SS[2] ss = [SS(&a), SS(null)];
1416 assert( doesPointTo(ss, a)); //The array contains a struct that points to a
1417 assert(!doesPointTo(ss, b)); //The array doesn't contains a struct that points to b
1418 assert(!doesPointTo(ss, ss)); //The array doesn't point itself.
1420 // https://issues.dlang.org/show_bug.cgi?id=20426
1421 align((void*).alignof) void[32] voidArr = void;
1422 (cast(void*[]) voidArr[])[] = null; // Ensure no false pointers
1424 // zeroed void ranges can't point at anything
1425 assert(!mayPointTo(voidArr, a));
1426 assert(!mayPointTo(voidArr, b));
1428 *cast(void**) &voidArr[16] = &a; // Pointers should be found
1430 alias SA = void[size_t.sizeof + 3];
1431 SA *smallArr1 = cast(SA*)&voidArr;
1432 SA *smallArr2 = cast(SA*)&(voidArr[16]);
1434 // But it should only consider properly aligned pointers
1435 // Write single bytes to avoid issues due to misaligned writes
1436 void*[1] tmp = [&b];
1437 (cast(ubyte[]) voidArr[3 .. 3 + (void*).sizeof])[] = cast(ubyte[]) tmp[];
1440 assert( mayPointTo(*smallArr2, a));
1441 assert(!mayPointTo(*smallArr1, b));
1443 assert(!doesPointTo(voidArr, a)); // Value might be a false pointer
1444 assert(!doesPointTo(voidArr, b));
1446 SA *smallArr3 = cast(SA *) &voidArr[13]; // Works for weird sizes/alignments
1447 assert( mayPointTo(*smallArr3, a));
1448 assert(!mayPointTo(*smallArr3, b));
1450 assert(!doesPointTo(*smallArr3, a));
1451 assert(!doesPointTo(*smallArr3, b));
1453 auto v3 = cast(void[3]*) &voidArr[16]; // Arrays smaller than pointers are ignored
1454 assert(!mayPointTo(*v3, a));
1455 assert(!mayPointTo(*v3, b));
1457 assert(!doesPointTo(*v3, a));
1458 assert(!doesPointTo(*v3, b));
1460 assert(mayPointTo(voidArr, a)); // slice-contiaining void[N] might point at anything
1461 assert(mayPointTo(voidArr, b));
1463 static assert(() {
1464 void[16] arr1 = void;
1465 void[size_t.sizeof] arr2 = void;
1466 int var;
1467 return mayPointTo(arr1, var) && !doesPointTo(arr1, var) &&
1468 mayPointTo(arr2, var) && !doesPointTo(arr2, var);
1469 }());
1473 @system unittest //Unions
1475 int i;
1476 union U //Named union
1478 size_t asInt = 0;
1479 int* asPointer;
1481 struct S
1483 union //Anonymous union
1485 size_t asInt = 0;
1486 int* asPointer;
1490 U u;
1491 S s;
1492 assert(!doesPointTo(u, i));
1493 assert(!doesPointTo(s, i));
1494 assert(!mayPointTo(u, i));
1495 assert(!mayPointTo(s, i));
1497 u.asPointer = &i;
1498 s.asPointer = &i;
1499 assert(!doesPointTo(u, i));
1500 assert(!doesPointTo(s, i));
1501 assert( mayPointTo(u, i));
1502 assert( mayPointTo(s, i));
1504 u.asInt = cast(size_t)&i;
1505 s.asInt = cast(size_t)&i;
1506 assert(!doesPointTo(u, i));
1507 assert(!doesPointTo(s, i));
1508 assert( mayPointTo(u, i));
1509 assert( mayPointTo(s, i));
1512 @system unittest //Classes
1514 int i;
1515 static class A
1517 int* p;
1519 A a = new A, b = a;
1520 assert(!doesPointTo(a, b)); //a does not point to b
1521 a.p = &i;
1522 assert(!doesPointTo(a, i)); //a does not point to i
1524 @safe unittest //alias this test
1526 static int i;
1527 static int j;
1528 struct S
1530 int* p;
1531 @property int* foo(){return &i;}
1532 alias foo this;
1534 assert(is(S : int*));
1535 S s = S(&j);
1536 assert(!doesPointTo(s, i));
1537 assert( doesPointTo(s, j));
1538 assert( doesPointTo(cast(int*) s, i));
1539 assert(!doesPointTo(cast(int*) s, j));
1543 Returns true if the field at index `i` in $(D T) shares its address with another field.
1545 Note: This does not merely check if the field is a member of an union, but also that
1546 it is not a single child.
1548 package enum isUnionAliased(T, size_t i) = isUnionAliasedImpl!T(T.tupleof[i].offsetof);
1549 private bool isUnionAliasedImpl(T)(size_t offset)
1551 int count = 0;
1552 foreach (i, U; typeof(T.tupleof))
1553 if (T.tupleof[i].offsetof == offset)
1554 ++count;
1555 return count >= 2;
1558 @safe unittest
1560 static struct S
1562 int a0; //Not aliased
1563 union
1565 int a1; //Not aliased
1567 union
1569 int a2; //Aliased
1570 int a3; //Aliased
1572 union A4
1574 int b0; //Not aliased
1576 A4 a4;
1577 union A5
1579 int b0; //Aliased
1580 int b1; //Aliased
1582 A5 a5;
1585 static assert(!isUnionAliased!(S, 0)); //a0;
1586 static assert(!isUnionAliased!(S, 1)); //a1;
1587 static assert( isUnionAliased!(S, 2)); //a2;
1588 static assert( isUnionAliased!(S, 3)); //a3;
1589 static assert(!isUnionAliased!(S, 4)); //a4;
1590 static assert(!isUnionAliased!(S.A4, 0)); //a4.b0;
1591 static assert(!isUnionAliased!(S, 5)); //a5;
1592 static assert( isUnionAliased!(S.A5, 0)); //a5.b0;
1593 static assert( isUnionAliased!(S.A5, 1)); //a5.b1;
1596 version (CRuntime_Glibc) version = GNU_STRERROR;
1597 version (CRuntime_UClibc) version = GNU_STRERROR;
1599 package string errnoString(int errno) nothrow @trusted
1601 import core.stdc.string : strlen;
1602 version (GNU_STRERROR)
1604 import core.stdc.string : strerror_r;
1605 char[1024] buf = void;
1606 auto s = strerror_r(errno, buf.ptr, buf.length);
1608 else version (Posix)
1610 // XSI-compliant
1611 import core.stdc.string : strerror_r;
1612 char[1024] buf = void;
1613 const(char)* s;
1614 if (strerror_r(errno, buf.ptr, buf.length) == 0)
1615 s = buf.ptr;
1616 else
1617 return "Unknown error";
1619 else
1621 import core.stdc.string : strerror;
1622 auto s = strerror(errno);
1624 return s[0 .. s.strlen].idup;
1627 /*********************
1628 * Thrown if errors that set `errno` occur.
1630 class ErrnoException : Exception
1632 /// Operating system error code.
1633 final @property uint errno() nothrow pure scope @nogc @safe { return _errno; }
1634 private uint _errno;
1635 /// Localized error message generated through $(REF strerror_r, core,stdc,string) or $(REF strerror, core,stdc,string).
1636 final @property string errnoMsg() nothrow pure scope @nogc @safe { return _errnoMsg; }
1637 private string _errnoMsg;
1638 /// Constructor which takes an error message. The current global $(REF errno, core,stdc,errno) value is used as error code.
1639 this(string msg, string file = null, size_t line = 0) @safe
1641 import core.stdc.errno : errno;
1642 this(msg, errno, file, line);
1644 /// Constructor which takes an error message and error code.
1645 this(string msg, int errno, string file = null, size_t line = 0) @safe
1647 _errno = errno;
1648 _errnoMsg = errnoString(errno);
1649 super(msg ~ " (" ~ errnoMsg ~ ")", file, line);
1654 @safe unittest
1656 import core.stdc.errno : EAGAIN;
1657 auto ex = new ErrnoException("oh no", EAGAIN);
1658 assert(ex.errno == EAGAIN);
1661 /// errno is used by default if no explicit error code is provided
1662 @safe unittest
1664 import core.stdc.errno : errno, EAGAIN;
1666 auto old = errno;
1667 scope(exit) errno = old;
1669 // fake that errno got set by the callee
1670 errno = EAGAIN;
1671 auto ex = new ErrnoException("oh no");
1672 assert(ex.errno == EAGAIN);
1676 ML-style functional exception handling. Runs the supplied expression and
1677 returns its result. If the expression throws a `Throwable`, runs the
1678 supplied error handler instead and return its result. The error handler's
1679 type must be the same as the expression's type.
1681 Params:
1682 E = The type of `Throwable`s to catch. Defaults to `Exception`
1683 T1 = The type of the expression.
1684 T2 = The return type of the error handler.
1685 expression = The expression to run and return its result.
1686 errorHandler = The handler to run if the expression throwed.
1688 Returns:
1689 expression, if it does not throw. Otherwise, returns the result of
1690 errorHandler.
1692 //lazy version
1693 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler)
1695 static assert(!is(typeof(return) == void),
1696 "The error handler's return value("
1697 ~ T2.stringof ~
1698 ") does not have a common type with the expression("
1699 ~ T1.stringof ~
1700 ")."
1704 return expression();
1706 catch (E)
1708 return errorHandler();
1712 ///ditto
1713 //delegate version
1714 CommonType!(T1, T2) ifThrown(E : Throwable, T1, T2)(lazy scope T1 expression, scope T2 delegate(E) errorHandler)
1716 static assert(!is(typeof(return) == void),
1717 "The error handler's return value("
1718 ~ T2.stringof ~
1719 ") does not have a common type with the expression("
1720 ~ T1.stringof ~
1721 ")."
1725 return expression();
1727 catch (E e)
1729 return errorHandler(e);
1733 ///ditto
1734 //delegate version, general overload to catch any Exception
1735 CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler)
1737 static assert(!is(typeof(return) == void),
1738 "The error handler's return value("
1739 ~ T2.stringof ~
1740 ") does not have a common type with the expression("
1741 ~ T1.stringof ~
1742 ")."
1746 return expression();
1748 catch (Exception e)
1750 return errorHandler(e);
1754 /// Revert to a default value upon an error:
1755 @safe unittest
1757 import std.conv : to;
1758 assert("x".to!int.ifThrown(0) == 0);
1762 Chain multiple calls to ifThrown, each capturing errors from the
1763 entire preceding expression.
1765 @safe unittest
1767 import std.conv : ConvException, to;
1768 string s = "true";
1769 assert(s.to!int.ifThrown(cast(int) s.to!double)
1770 .ifThrown(cast(int) s.to!bool) == 1);
1772 s = "2.0";
1773 assert(s.to!int.ifThrown(cast(int) s.to!double)
1774 .ifThrown(cast(int) s.to!bool) == 2);
1776 // Respond differently to different types of errors
1777 alias orFallback = (lazy a) => a.ifThrown!ConvException("not a number")
1778 .ifThrown!Exception("number too small");
1780 assert(orFallback(enforce("x".to!int < 1).to!string) == "not a number");
1781 assert(orFallback(enforce("2".to!int < 1).to!string) == "number too small");
1785 The expression and the errorHandler must have a common type they can both
1786 be implicitly casted to, and that type will be the type of the compound
1787 expression.
1789 @safe unittest
1791 // null and new Object have a common type(Object).
1792 static assert(is(typeof(null.ifThrown(new Object())) == Object));
1793 static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1795 // 1 and new Object do not have a common type.
1796 static assert(!__traits(compiles, 1.ifThrown(new Object())));
1797 static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1800 /// Use a lambda to get the thrown object.
1801 @system unittest
1803 import std.format : format;
1804 assert("%s".format.ifThrown!Exception(e => typeid(e).name) == "std.format.FormatException");
1807 //Verify Examples
1808 @system unittest
1810 import std.conv;
1811 import std.string;
1812 //Revert to a default value upon an error:
1813 assert("x".to!int().ifThrown(0) == 0);
1815 //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1816 string s="true";
1817 assert(s.to!int().
1818 ifThrown(cast(int) s.to!double()).
1819 ifThrown(cast(int) s.to!bool())
1820 == 1);
1822 //Respond differently to different types of errors
1823 assert(enforce("x".to!int() < 1).to!string()
1824 .ifThrown!ConvException("not a number")
1825 .ifThrown!Exception("number too small")
1826 == "not a number");
1828 //null and new Object have a common type(Object).
1829 static assert(is(typeof(null.ifThrown(new Object())) == Object));
1830 static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1832 //1 and new Object do not have a common type.
1833 static assert(!__traits(compiles, 1.ifThrown(new Object())));
1834 static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1836 //Use a lambda to get the thrown object.
1837 assert("%s".format().ifThrown(e => typeid(e).name) == "std.format.FormatException");
1840 @system unittest
1842 import core.exception;
1843 import std.conv;
1844 import std.string;
1845 //Basic behaviour - all versions.
1846 assert("1".to!int().ifThrown(0) == 1);
1847 assert("x".to!int().ifThrown(0) == 0);
1848 assert("1".to!int().ifThrown!ConvException(0) == 1);
1849 assert("x".to!int().ifThrown!ConvException(0) == 0);
1850 assert("1".to!int().ifThrown(e=>0) == 1);
1851 assert("x".to!int().ifThrown(e=>0) == 0);
1852 static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1854 assert("1".to!int().ifThrown!ConvException(e=>0) == 1);
1855 assert("x".to!int().ifThrown!ConvException(e=>0) == 0);
1858 //Exceptions other than stated not caught.
1859 assert("x".to!int().ifThrown!StringException(0).collectException!ConvException() !is null);
1860 static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1862 assert("x".to!int().ifThrown!StringException(e=>0).collectException!ConvException() !is null);
1865 //Default does not include errors.
1866 int throwRangeError() { throw new RangeError; }
1867 assert(throwRangeError().ifThrown(0).collectException!RangeError() !is null);
1868 assert(throwRangeError().ifThrown(e=>0).collectException!RangeError() !is null);
1870 //Incompatible types are not accepted.
1871 static assert(!__traits(compiles, 1.ifThrown(new Object())));
1872 static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1873 static assert(!__traits(compiles, 1.ifThrown(e=>new Object())));
1874 static assert(!__traits(compiles, (new Object()).ifThrown(e=>1)));
1877 version (StdUnittest) package
1878 void assertCTFEable(alias dg)()
1880 static assert({ cast(void) dg(); return true; }());
1881 cast(void) dg();
1884 /** This `enum` is used to select the primitives of the range to handle by the
1885 $(LREF handle) range wrapper. The values of the `enum` can be `OR`'d to
1886 select multiple primitives to be handled.
1888 `RangePrimitive.access` is a shortcut for the access primitives; `front`,
1889 `back` and `opIndex`.
1891 `RangePrimitive.pop` is a shortcut for the mutating primitives;
1892 `popFront` and `popBack`.
1894 enum RangePrimitive
1896 front = 0b00_0000_0001, ///
1897 back = 0b00_0000_0010, /// Ditto
1898 popFront = 0b00_0000_0100, /// Ditto
1899 popBack = 0b00_0000_1000, /// Ditto
1900 empty = 0b00_0001_0000, /// Ditto
1901 save = 0b00_0010_0000, /// Ditto
1902 length = 0b00_0100_0000, /// Ditto
1903 opDollar = 0b00_1000_0000, /// Ditto
1904 opIndex = 0b01_0000_0000, /// Ditto
1905 opSlice = 0b10_0000_0000, /// Ditto
1906 access = front | back | opIndex, /// Ditto
1907 pop = popFront | popBack, /// Ditto
1911 pure @safe unittest
1913 import std.algorithm.comparison : equal;
1914 import std.algorithm.iteration : map, splitter;
1915 import std.conv : to, ConvException;
1917 auto s = "12,1337z32,54,2,7,9,1z,6,8";
1919 // The next line composition will throw when iterated
1920 // as some elements of the input do not convert to integer
1921 auto r = s.splitter(',').map!(a => to!int(a));
1923 // Substitute 0 for cases of ConvException
1924 auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
1925 assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
1929 pure @safe unittest
1931 import std.algorithm.comparison : equal;
1932 import std.range : retro;
1933 import std.utf : UTFException;
1935 auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
1937 auto handled = str.handle!(UTFException, RangePrimitive.access,
1938 (e, r) => ' '); // Replace invalid code points with spaces
1940 assert(handled.equal("hello world")); // `front` is handled,
1941 assert(handled.retro.equal("dlrow olleh")); // as well as `back`
1944 /** Handle exceptions thrown from range primitives.
1946 Use the $(LREF RangePrimitive) enum to specify which primitives to _handle.
1947 Multiple range primitives can be handled at once by using the `OR` operator
1948 or the pseudo-primitives `RangePrimitive.access` and `RangePrimitive.pop`.
1949 All handled primitives must have return types or values compatible with the
1950 user-supplied handler.
1952 Params:
1953 E = The type of `Throwable` to _handle.
1954 primitivesToHandle = Set of range primitives to _handle.
1955 handler = The callable that is called when a handled primitive throws a
1956 `Throwable` of type `E`. The handler must accept arguments of
1957 the form $(D E, ref IRange) and its return value is used as the primitive's
1958 return value whenever `E` is thrown. For `opIndex`, the handler can
1959 optionally recieve a third argument; the index that caused the exception.
1960 input = The range to _handle.
1962 Returns: A wrapper `struct` that preserves the range interface of `input`.
1964 Note:
1965 Infinite ranges with slicing support must return an instance of
1966 $(REF Take, std,range) when sliced with a specific lower and upper
1967 bound (see $(REF hasSlicing, std,range,primitives)); `handle` deals with
1968 this by `take`ing 0 from the return value of the handler function and
1969 returning that when an exception is caught.
1971 auto handle(E : Throwable, RangePrimitive primitivesToHandle, alias handler, Range)(Range input)
1972 if (isInputRange!Range)
1974 static struct Handler
1976 private Range range;
1978 static if (isForwardRange!Range)
1980 @property typeof(this) save()
1982 static if (primitivesToHandle & RangePrimitive.save)
1986 return typeof(this)(range.save);
1988 catch (E exception)
1990 return typeof(this)(handler(exception, this.range));
1993 else
1994 return typeof(this)(range.save);
1998 static if (isInfinite!Range)
2000 enum bool empty = false;
2002 else
2004 @property bool empty()
2006 static if (primitivesToHandle & RangePrimitive.empty)
2010 return this.range.empty;
2012 catch (E exception)
2014 return handler(exception, this.range);
2017 else
2018 return this.range.empty;
2022 @property auto ref front()
2024 static if (primitivesToHandle & RangePrimitive.front)
2028 return this.range.front;
2030 catch (E exception)
2032 return handler(exception, this.range);
2035 else
2036 return this.range.front;
2039 void popFront()
2041 static if (primitivesToHandle & RangePrimitive.popFront)
2045 this.range.popFront();
2047 catch (E exception)
2049 handler(exception, this.range);
2052 else
2053 this.range.popFront();
2056 static if (isBidirectionalRange!Range)
2058 @property auto ref back()
2060 static if (primitivesToHandle & RangePrimitive.back)
2064 return this.range.back;
2066 catch (E exception)
2068 return handler(exception, this.range);
2071 else
2072 return this.range.back;
2075 void popBack()
2077 static if (primitivesToHandle & RangePrimitive.popBack)
2081 this.range.popBack();
2083 catch (E exception)
2085 handler(exception, this.range);
2088 else
2089 this.range.popBack();
2093 static if (isRandomAccessRange!Range)
2095 auto ref opIndex(size_t index)
2097 static if (primitivesToHandle & RangePrimitive.opIndex)
2101 return this.range[index];
2103 catch (E exception)
2105 static if (__traits(compiles, handler(exception, this.range, index)))
2106 return handler(exception, this.range, index);
2107 else
2108 return handler(exception, this.range);
2111 else
2112 return this.range[index];
2116 static if (hasLength!Range)
2118 @property auto length()
2120 static if (primitivesToHandle & RangePrimitive.length)
2124 return this.range.length;
2126 catch (E exception)
2128 return handler(exception, this.range);
2131 else
2132 return this.range.length;
2136 static if (hasSlicing!Range)
2138 static if (hasLength!Range)
2140 typeof(this) opSlice(size_t lower, size_t upper)
2142 static if (primitivesToHandle & RangePrimitive.opSlice)
2146 return typeof(this)(this.range[lower .. upper]);
2148 catch (E exception)
2150 return typeof(this)(handler(exception, this.range));
2153 else
2154 return typeof(this)(this.range[lower .. upper]);
2157 else static if (is(typeof(Range.init[size_t.init .. $])))
2159 import std.range : Take, takeExactly;
2160 static struct DollarToken {}
2161 enum opDollar = DollarToken.init;
2163 typeof(this) opSlice(size_t lower, DollarToken)
2165 static if (primitivesToHandle & RangePrimitive.opSlice)
2169 return typeof(this)(this.range[lower .. $]);
2171 catch (E exception)
2173 return typeof(this)(handler(exception, this.range));
2176 else
2177 return typeof(this)(this.range[lower .. $]);
2180 Take!Handler opSlice(size_t lower, size_t upper)
2182 static if (primitivesToHandle & RangePrimitive.opSlice)
2186 return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2188 catch (E exception)
2190 return takeExactly(typeof(this)(handler(exception, this.range)), 0);
2193 else
2194 return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2200 return Handler(input);
2204 pure @safe unittest
2206 import std.algorithm.comparison : equal;
2207 import std.algorithm.iteration : map, splitter;
2208 import std.conv : to, ConvException;
2210 auto s = "12,1337z32,54,2,7,9,1z,6,8";
2212 // The next line composition will throw when iterated
2213 // as some elements of the input do not convert to integer
2214 auto r = s.splitter(',').map!(a => to!int(a));
2216 // Substitute 0 for cases of ConvException
2217 auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
2218 assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
2222 pure @safe unittest
2224 import std.algorithm.comparison : equal;
2225 import std.range : retro;
2226 import std.utf : UTFException;
2228 auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
2230 auto handled = str.handle!(UTFException, RangePrimitive.access,
2231 (e, r) => ' '); // Replace invalid code points with spaces
2233 assert(handled.equal("hello world")); // `front` is handled,
2234 assert(handled.retro.equal("dlrow olleh")); // as well as `back`
2237 pure nothrow @safe unittest
2239 static struct ThrowingRange
2241 pure @safe:
2242 @property bool empty()
2244 throw new Exception("empty has thrown");
2247 @property int front()
2249 throw new Exception("front has thrown");
2252 @property int back()
2254 throw new Exception("back has thrown");
2257 void popFront()
2259 throw new Exception("popFront has thrown");
2262 void popBack()
2264 throw new Exception("popBack has thrown");
2267 int opIndex(size_t)
2269 throw new Exception("opIndex has thrown");
2272 ThrowingRange opSlice(size_t, size_t)
2274 throw new Exception("opSlice has thrown");
2277 @property size_t length()
2279 throw new Exception("length has thrown");
2282 alias opDollar = length;
2284 @property ThrowingRange save()
2286 throw new Exception("save has thrown");
2290 static assert(isInputRange!ThrowingRange);
2291 static assert(isForwardRange!ThrowingRange);
2292 static assert(isBidirectionalRange!ThrowingRange);
2293 static assert(hasSlicing!ThrowingRange);
2294 static assert(hasLength!ThrowingRange);
2296 auto f = ThrowingRange();
2297 auto fb = f.handle!(Exception, RangePrimitive.front | RangePrimitive.back,
2298 (e, r) => -1)();
2299 assert(fb.front == -1);
2300 assert(fb.back == -1);
2301 assertThrown(fb.popFront());
2302 assertThrown(fb.popBack());
2303 assertThrown(fb.empty);
2304 assertThrown(fb.save);
2305 assertThrown(fb[0]);
2307 auto accessRange = f.handle!(Exception, RangePrimitive.access,
2308 (e, r) => -1);
2309 assert(accessRange.front == -1);
2310 assert(accessRange.back == -1);
2311 assert(accessRange[0] == -1);
2312 assertThrown(accessRange.popFront());
2313 assertThrown(accessRange.popBack());
2315 auto pfb = f.handle!(Exception, RangePrimitive.pop, (e, r) => -1)();
2317 pfb.popFront(); // this would throw otherwise
2318 pfb.popBack(); // this would throw otherwise
2320 auto em = f.handle!(Exception,
2321 RangePrimitive.empty, (e, r) => false)();
2323 assert(!em.empty);
2325 auto arr = f.handle!(Exception,
2326 RangePrimitive.opIndex, (e, r) => 1337)();
2328 assert(arr[0] == 1337);
2330 auto arr2 = f.handle!(Exception,
2331 RangePrimitive.opIndex, (e, r, i) => i)();
2333 assert(arr2[0] == 0);
2334 assert(arr2[1337] == 1337);
2336 auto save = f.handle!(Exception,
2337 RangePrimitive.save,
2338 function(Exception e, ref ThrowingRange r) {
2339 return ThrowingRange();
2340 })();
2342 save.save;
2344 auto slice = f.handle!(Exception,
2345 RangePrimitive.opSlice, (e, r) => ThrowingRange())();
2347 auto sliced = slice[0 .. 1337]; // this would throw otherwise
2349 static struct Infinite
2351 import std.range : Take;
2352 pure @safe:
2353 enum bool empty = false;
2354 int front() { assert(false); }
2355 void popFront() { assert(false); }
2356 Infinite save() @property { assert(false); }
2357 static struct DollarToken {}
2358 enum opDollar = DollarToken.init;
2359 Take!Infinite opSlice(size_t, size_t) { assert(false); }
2360 Infinite opSlice(size_t, DollarToken)
2362 throw new Exception("opSlice has thrown");
2366 static assert(isInputRange!Infinite);
2367 static assert(isInfinite!Infinite);
2368 static assert(hasSlicing!Infinite);
2370 assertThrown(Infinite()[0 .. $]);
2372 auto infinite = Infinite.init.handle!(Exception,
2373 RangePrimitive.opSlice, (e, r) => Infinite())();
2375 auto infSlice = infinite[0 .. $]; // this would throw otherwise
2380 Convenience mixin for trivially sub-classing exceptions
2382 Even trivially sub-classing an exception involves writing boilerplate code
2383 for the constructor to: 1$(RPAREN) correctly pass in the source file and line number
2384 the exception was thrown from; 2$(RPAREN) be usable with $(LREF enforce) which
2385 expects exception constructors to take arguments in a fixed order. This
2386 mixin provides that boilerplate code.
2388 Note however that you need to mark the $(B mixin) line with at least a
2389 minimal (i.e. just $(B ///)) DDoc comment if you want the mixed-in
2390 constructors to be documented in the newly created Exception subclass.
2392 $(RED Current limitation): Due to
2393 $(LINK2 https://issues.dlang.org/show_bug.cgi?id=11500, bug #11500),
2394 currently the constructors specified in this mixin cannot be overloaded with
2395 any other custom constructors. Thus this mixin can currently only be used
2396 when no such custom constructors need to be explicitly specified.
2398 mixin template basicExceptionCtors()
2401 Params:
2402 msg = The message for the exception.
2403 file = The file where the exception occurred.
2404 line = The line number where the exception occurred.
2405 next = The previous exception in the chain of exceptions, if any.
2407 this(string msg, string file = __FILE__, size_t line = __LINE__,
2408 Throwable next = null) @nogc @safe pure nothrow
2410 super(msg, file, line, next);
2414 Params:
2415 msg = The message for the exception.
2416 next = The previous exception in the chain of exceptions.
2417 file = The file where the exception occurred.
2418 line = The line number where the exception occurred.
2420 this(string msg, Throwable next, string file = __FILE__,
2421 size_t line = __LINE__) @nogc @safe pure nothrow
2423 super(msg, file, line, next);
2428 @safe unittest
2430 class MeaCulpa: Exception
2433 mixin basicExceptionCtors;
2437 throw new MeaCulpa("test");
2438 catch (MeaCulpa e)
2440 assert(e.msg == "test");
2441 assert(e.file == __FILE__);
2442 assert(e.line == __LINE__ - 5);
2446 @safe pure nothrow unittest
2448 class TestException : Exception { mixin basicExceptionCtors; }
2449 auto e = new Exception("msg");
2450 auto te1 = new TestException("foo");
2451 auto te2 = new TestException("foo", e);
2454 @safe unittest
2456 class TestException : Exception { mixin basicExceptionCtors; }
2457 auto e = new Exception("!!!");
2459 auto te1 = new TestException("message", "file", 42, e);
2460 assert(te1.msg == "message");
2461 assert(te1.file == "file");
2462 assert(te1.line == 42);
2463 assert(te1.next is e);
2465 auto te2 = new TestException("message", e, "file", 42);
2466 assert(te2.msg == "message");
2467 assert(te2.file == "file");
2468 assert(te2.line == 42);
2469 assert(te2.next is e);
2471 auto te3 = new TestException("foo");
2472 assert(te3.msg == "foo");
2473 assert(te3.file == __FILE__);
2474 assert(te3.line == __LINE__ - 3);
2475 assert(te3.next is null);
2477 auto te4 = new TestException("foo", e);
2478 assert(te4.msg == "foo");
2479 assert(te4.file == __FILE__);
2480 assert(te4.line == __LINE__ - 3);
2481 assert(te4.next is e);