1 // Written in the D programming language.
2 
3 /++
4     This module defines functions related to exceptions and general error
5     handling. It also defines functions intended to aid in unit testing.
6 
7 $(SCRIPT inhibitQuickIndex = 1;)
8 $(BOOKTABLE,
9 $(TR $(TH Category) $(TH Functions))
10 $(TR $(TD Assumptions) $(TD
11         $(LREF assertNotThrown)
12         $(LREF assertThrown)
13         $(LREF assumeUnique)
14         $(LREF assumeWontThrow)
15         $(LREF mayPointTo)
16 ))
17 $(TR $(TD Enforce) $(TD
18         $(LREF doesPointTo)
19         $(LREF enforce)
20         $(LREF enforceEx)
21         $(LREF errnoEnforce)
22 ))
23 $(TR $(TD Handlers) $(TD
24         $(LREF collectException)
25         $(LREF collectExceptionMsg)
26         $(LREF ifThrown)
27         $(LREF handle)
28 ))
29 $(TR $(TD Other) $(TD
30         $(LREF basicExceptionCtors)
31         $(LREF emptyExceptionMsg)
32         $(LREF ErrnoException)
33         $(LREF RangePrimitive)
34 ))
35 )
36 
37     Synopsis of some of std.exception's functions:
38     --------------------
39     string synopsis()
40     {
41         FILE* f = enforce(fopen("some/file"));
42         // f is not null from here on
43         FILE* g = enforce!WriteException(fopen("some/other/file", "w"));
44         // g is not null from here on
45 
46         Exception e = collectException(write(g, readln(f)));
47         if (e)
48         {
49             ... an exception occurred...
50             ... We have the exception to play around with...
51         }
52 
53         string msg = collectExceptionMsg(write(g, readln(f)));
54         if (msg)
55         {
56             ... an exception occurred...
57             ... We have the message from the exception but not the exception...
58         }
59 
60         char[] line;
61         enforce(readln(f, line));
62         return assumeUnique(line);
63     }
64     --------------------
65 
66     Copyright: Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-.
67     License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0)
68     Authors:   $(HTTP erdani.org, Andrei Alexandrescu) and Jonathan M Davis
69     Source:    $(PHOBOSSRC std/_exception.d)
70 
71  +/
72 module std.exception;
73 
74 import std.range.primitives;
75 import std.traits;
76 
77 /++
78     Asserts that the given expression does $(I not) throw the given type
79     of $(D Throwable). If a $(D Throwable) of the given type is thrown,
80     it is caught and does not escape assertNotThrown. Rather, an
81     $(D AssertError) is thrown. However, any other $(D Throwable)s will escape.
82 
83     Params:
84         T          = The $(D Throwable) to test for.
85         expression = The expression to test.
86         msg        = Optional message to output on test failure.
87                      If msg is empty, and the thrown exception has a
88                      non-empty msg field, the exception's msg field
89                      will be output on test failure.
90         file       = The file where the error occurred.
91                      Defaults to $(D __FILE__).
92         line       = The line where the error occurred.
93                      Defaults to $(D __LINE__).
94 
95     Throws:
96         $(D AssertError) if the given $(D Throwable) is thrown.
97 
98     Returns:
99         the result of `expression`.
100  +/
101 auto assertNotThrown(T : Throwable = Exception, E)
102                     (lazy E expression,
103                      string msg = null,
104                      string file = __FILE__,
105                      size_t line = __LINE__)
106 {
107     import core.exception : AssertError;
108     try
109     {
110         return expression();
111     }
catch(T t)112     catch (T t)
113     {
114         immutable message = msg.length == 0 ? t.msg : msg;
115         immutable tail = message.length == 0 ? "." : ": " ~ message;
116         throw new AssertError("assertNotThrown failed: " ~ T.stringof ~ " was thrown" ~ tail, file, line, t);
117     }
118 }
119 ///
120 @system unittest
121 {
122     import core.exception : AssertError;
123 
124     import std.string;
125     assertNotThrown!StringException(enforce!StringException(true, "Error!"));
126 
127     //Exception is the default.
128     assertNotThrown(enforce!StringException(true, "Error!"));
129 
130     assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
131                enforce!StringException(false, "Error!"))) ==
132            `assertNotThrown failed: StringException was thrown: Error!`);
133 }
134 @system unittest
135 {
136     import core.exception : AssertError;
137     import std.string;
138     assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
139                enforce!StringException(false, ""), "Error!")) ==
140            `assertNotThrown failed: StringException was thrown: Error!`);
141 
142     assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
143                enforce!StringException(false, ""))) ==
144            `assertNotThrown failed: StringException was thrown.`);
145 
146     assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
147                enforce!StringException(false, ""), "")) ==
148            `assertNotThrown failed: StringException was thrown.`);
149 }
150 
151 @system unittest
152 {
153     import core.exception : AssertError;
154 
throwEx(Throwable t)155     void throwEx(Throwable t) { throw t; }
nothrowEx()156     bool nothrowEx() { return true; }
157 
158     try
159     {
160         assert(assertNotThrown!Exception(nothrowEx()));
161     }
162     catch (AssertError) assert(0);
163 
164     try
165     {
166         assert(assertNotThrown!Exception(nothrowEx(), "It's a message"));
167     }
168     catch (AssertError) assert(0);
169 
170     try
171     {
172         assert(assertNotThrown!AssertError(nothrowEx()));
173     }
174     catch (AssertError) assert(0);
175 
176     try
177     {
178         assert(assertNotThrown!AssertError(nothrowEx(), "It's a message"));
179     }
180     catch (AssertError) assert(0);
181 
182     {
183         bool thrown = false;
184         try
185         {
186             assertNotThrown!Exception(
187                 throwEx(new Exception("It's an Exception")));
188         }
189         catch (AssertError) thrown = true;
190         assert(thrown);
191     }
192 
193     {
194         bool thrown = false;
195         try
196         {
197             assertNotThrown!Exception(
198                 throwEx(new Exception("It's an Exception")), "It's a message");
199         }
200         catch (AssertError) thrown = true;
201         assert(thrown);
202     }
203 
204     {
205         bool thrown = false;
206         try
207         {
208             assertNotThrown!AssertError(
209                 throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)));
210         }
211         catch (AssertError) thrown = true;
212         assert(thrown);
213     }
214 
215     {
216         bool thrown = false;
217         try
218         {
219             assertNotThrown!AssertError(
220                 throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)),
221                         "It's a message");
222         }
223         catch (AssertError) thrown = true;
224         assert(thrown);
225     }
226 }
227 
228 /++
229     Asserts that the given expression throws the given type of $(D Throwable).
230     The $(D Throwable) is caught and does not escape assertThrown. However,
231     any other $(D Throwable)s $(I will) escape, and if no $(D Throwable)
232     of the given type is thrown, then an $(D AssertError) is thrown.
233 
234     Params:
235         T          = The $(D Throwable) to test for.
236         expression = The expression to test.
237         msg        = Optional message to output on test failure.
238         file       = The file where the error occurred.
239                      Defaults to $(D __FILE__).
240         line       = The line where the error occurred.
241                      Defaults to $(D __LINE__).
242 
243     Throws:
244         $(D AssertError) if the given $(D Throwable) is not thrown.
245   +/
246 void assertThrown(T : Throwable = Exception, E)
247                  (lazy E expression,
248                   string msg = null,
249                   string file = __FILE__,
250                   size_t line = __LINE__)
251 {
252     import core.exception : AssertError;
253 
254     try
255         expression();
256     catch (T)
257         return;
258     throw new AssertError("assertThrown failed: No " ~ T.stringof ~ " was thrown"
259                                  ~ (msg.length == 0 ? "." : ": ") ~ msg,
260                           file, line);
261 }
262 ///
263 @system unittest
264 {
265     import core.exception : AssertError;
266     import std.string;
267 
268     assertThrown!StringException(enforce!StringException(false, "Error!"));
269 
270     //Exception is the default.
271     assertThrown(enforce!StringException(false, "Error!"));
272 
273     assert(collectExceptionMsg!AssertError(assertThrown!StringException(
274                enforce!StringException(true, "Error!"))) ==
275            `assertThrown failed: No StringException was thrown.`);
276 }
277 
278 @system unittest
279 {
280     import core.exception : AssertError;
281 
throwEx(Throwable t)282     void throwEx(Throwable t) { throw t; }
nothrowEx()283     void nothrowEx() { }
284 
285     try
286     {
287         assertThrown!Exception(throwEx(new Exception("It's an Exception")));
288     }
289     catch (AssertError) assert(0);
290 
291     try
292     {
293         assertThrown!Exception(throwEx(new Exception("It's an Exception")),
294                                "It's a message");
295     }
296     catch (AssertError) assert(0);
297 
298     try
299     {
300         assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
301                                                          __FILE__, __LINE__)));
302     }
303     catch (AssertError) assert(0);
304 
305     try
306     {
307         assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
308                                                          __FILE__, __LINE__)),
309                                  "It's a message");
310     }
311     catch (AssertError) assert(0);
312 
313 
314     {
315         bool thrown = false;
316         try
317             assertThrown!Exception(nothrowEx());
318         catch (AssertError)
319             thrown = true;
320 
321         assert(thrown);
322     }
323 
324     {
325         bool thrown = false;
326         try
327             assertThrown!Exception(nothrowEx(), "It's a message");
328         catch (AssertError)
329             thrown = true;
330 
331         assert(thrown);
332     }
333 
334     {
335         bool thrown = false;
336         try
337             assertThrown!AssertError(nothrowEx());
338         catch (AssertError)
339             thrown = true;
340 
341         assert(thrown);
342     }
343 
344     {
345         bool thrown = false;
346         try
347             assertThrown!AssertError(nothrowEx(), "It's a message");
348         catch (AssertError)
349             thrown = true;
350 
351         assert(thrown);
352     }
353 }
354 
355 
356 /++
357     Enforces that the given value is true.
358 
359     Params:
360         value = The value to test.
361         E = Exception type to throw if the value evalues to false.
362         msg = The error message to put in the exception if it is thrown.
363         file = The source file of the caller.
364         line = The line number of the caller.
365 
366     Returns: $(D value), if `cast(bool) value` is true. Otherwise,
367     $(D new Exception(msg)) is thrown.
368 
369     Note:
370         $(D enforce) is used to throw exceptions and is therefore intended to
371         aid in error handling. It is $(I not) intended for verifying the logic
372         of your program. That is what $(D assert) is for. Also, do not use
373         $(D enforce) inside of contracts (i.e. inside of $(D in) and $(D out)
374         blocks and $(D invariant)s), because they will be compiled out when
375         compiling with $(I -release). Use $(D assert) in contracts.
376 
377     Example:
378     --------------------
379     auto f = enforce(fopen("data.txt"));
380     auto line = readln(f);
381     enforce(line.length, "Expected a non-empty line.");
382     --------------------
383  +/
384 T enforce(E : Throwable = Exception, T)(T value, lazy const(char)[] msg = null,
385 string file = __FILE__, size_t line = __LINE__)
386 if (is(typeof({ if (!value) {} })))
387 {
388     if (!value) bailOut!E(file, line, msg);
389     return value;
390 }
391 
392 /++
393     Enforces that the given value is true.
394 
395     Params:
396         value = The value to test.
397         dg = The delegate to be called if the value evaluates to false.
398         file = The source file of the caller.
399         line = The line number of the caller.
400 
401     Returns: $(D value), if `cast(bool) value` is true. Otherwise, the given
402     delegate is called.
403 
404     The safety and purity of this function are inferred from $(D Dg)'s safety
405     and purity.
406  +/
407 T enforce(T, Dg, string file = __FILE__, size_t line = __LINE__)
408     (T value, scope Dg dg)
409 if (isSomeFunction!Dg && is(typeof( dg() )) &&
410     is(typeof({ if (!value) {} })))
411 {
412     if (!value) dg();
413     return value;
414 }
415 
416 private void bailOut(E : Throwable = Exception)(string file, size_t line, in char[] msg)
417 {
418     static if (is(typeof(new E(string.init, string.init, size_t.init))))
419     {
420         throw new E(msg ? msg.idup : "Enforcement failed", file, line);
421     }
422     else static if (is(typeof(new E(string.init, size_t.init))))
423     {
424         throw new E(file, line);
425     }
426     else
427     {
428         static assert(0, "Expected this(string, string, size_t) or this(string, size_t)" ~
429             " constructor for " ~ __traits(identifier, E));
430     }
431 }
432 
433 @safe unittest
434 {
435     assert(enforce(123) == 123);
436 
437     try
438     {
439         enforce(false, "error");
440         assert(false);
441     }
catch(Exception e)442     catch (Exception e)
443     {
444         assert(e.msg == "error");
445         assert(e.file == __FILE__);
446         assert(e.line == __LINE__-7);
447     }
448 }
449 
450 @safe unittest
451 {
452     // Issue 10510
453     extern(C) void cFoo() { }
454     enforce(false, &cFoo);
455 }
456 
457 // purity and safety inference test
458 @system unittest
459 {
460     import std.meta : AliasSeq;
461 
462     foreach (EncloseSafe; AliasSeq!(false, true))
463     foreach (EnclosePure; AliasSeq!(false, true))
464     {
465         foreach (BodySafe; AliasSeq!(false, true))
466         foreach (BodyPure; AliasSeq!(false, true))
467         {
468             enum code =
469                 "delegate void() " ~
470                 (EncloseSafe ? "@safe " : "") ~
471                 (EnclosePure ? "pure " : "") ~
472                 "{ enforce(true, { " ~
473                         "int n; " ~
474                         (BodySafe ? "" : "auto p = &n + 10; "    ) ~    // unsafe code
475                         (BodyPure ? "" : "static int g; g = 10; ") ~    // impure code
476                     "}); " ~
477                 "}";
478             enum expect =
479                 (BodySafe || !EncloseSafe) && (!EnclosePure || BodyPure);
480 
481             version (none)
482             pragma(msg, "safe = ", EncloseSafe?1:0, "/", BodySafe?1:0, ", ",
483                         "pure = ", EnclosePure?1:0, "/", BodyPure?1:0, ", ",
484                         "expect = ", expect?"OK":"NG", ", ",
485                         "code = ", code);
486 
487             static assert(__traits(compiles, mixin(code)()) == expect);
488         }
489     }
490 }
491 
492 // Test for bugzilla 8637
493 @system unittest
494 {
495     struct S
496     {
497         static int g;
498         ~this() {}  // impure & unsafe destructor
499         bool opCast(T:bool)() {
500             int* p = cast(int*) 0;   // unsafe operation
501             int n = g;              // impure operation
502             return true;
503         }
504     }
505     S s;
506 
507     enforce(s);
508     enforce(s, {});
509     enforce(s, new Exception(""));
510 
511     errnoEnforce(s);
512 
513     alias E1 = Exception;
514     static class E2 : Exception
515     {
516         this(string fn, size_t ln) { super("", fn, ln); }
517     }
518     static class E3 : Exception
519     {
520         this(string msg) { super(msg, __FILE__, __LINE__); }
521     }
522     enforce!E1(s);
523     enforce!E2(s);
524 }
525 
526 @safe unittest
527 {
528     // Issue 14685
529 
530     class E : Exception
531     {
532         this() { super("Not found"); }
533     }
534     static assert(!__traits(compiles, { enforce!E(false); }));
535 }
536 
537 /++
538     Enforces that the given value is true.
539 
540     Params:
541         value = The value to test.
542         ex = The exception to throw if the value evaluates to false.
543 
544     Returns: $(D value), if `cast(bool) value` is true. Otherwise, $(D ex) is
545     thrown.
546 
547     Example:
548     --------------------
549     auto f = enforce(fopen("data.txt"));
550     auto line = readln(f);
551     enforce(line.length, new IOException); // expect a non-empty line
552     --------------------
553  +/
554 T enforce(T)(T value, lazy Throwable ex)
555 {
556     if (!value) throw ex();
557     return value;
558 }
559 
560 @safe unittest
561 {
562     assertNotThrown(enforce(true, new Exception("this should not be thrown")));
563     assertThrown(enforce(false, new Exception("this should be thrown")));
564 }
565 
566 /++
567     Enforces that the given value is true, throwing an `ErrnoException` if it
568     is not.
569 
570     Params:
571         value = The value to test.
572         msg = The message to include in the `ErrnoException` if it is thrown.
573 
574     Returns: $(D value), if `cast(bool) value` is true. Otherwise,
575     $(D new ErrnoException(msg)) is thrown.  It is assumed that the last
576     operation set $(D errno) to an error code corresponding with the failed
577     condition.
578 
579     Example:
580     --------------------
581     auto f = errnoEnforce(fopen("data.txt"));
582     auto line = readln(f);
583     enforce(line.length); // expect a non-empty line
584     --------------------
585  +/
586 T errnoEnforce(T, string file = __FILE__, size_t line = __LINE__)
587     (T value, lazy string msg = null)
588 {
589     if (!value) throw new ErrnoException(msg, file, line);
590     return value;
591 }
592 
593 
594 /++
595     If $(D !value) is $(D false), $(D value) is returned. Otherwise,
596     $(D new E(msg, file, line)) is thrown. Or if $(D E) doesn't take a message
597     and can be constructed with $(D new E(file, line)), then
598     $(D new E(file, line)) will be thrown.
599 
600     This is legacy name, it is recommended to use $(D enforce!E) instead.
601 
602     Example:
603     --------------------
604     auto f = enforceEx!FileMissingException(fopen("data.txt"));
605     auto line = readln(f);
606     enforceEx!DataCorruptionException(line.length);
607     --------------------
608  +/
609 template enforceEx(E : Throwable)
610 if (is(typeof(new E("", __FILE__, __LINE__))))
611 {
612     /++ Ditto +/
enforceEx(T)613     T enforceEx(T)(T value, lazy string msg = "", string file = __FILE__, size_t line = __LINE__)
614     {
615         if (!value) throw new E(msg, file, line);
616         return value;
617     }
618 }
619 
620 /++ Ditto +/
621 template enforceEx(E : Throwable)
622 if (is(typeof(new E(__FILE__, __LINE__))) && !is(typeof(new E("", __FILE__, __LINE__))))
623 {
624     /++ Ditto +/
enforceEx(T)625     T enforceEx(T)(T value, string file = __FILE__, size_t line = __LINE__)
626     {
627         if (!value) throw new E(file, line);
628         return value;
629     }
630 }
631 
632 @system unittest
633 {
634     import core.exception : OutOfMemoryError;
635     import std.array : empty;
636     assertNotThrown(enforceEx!Exception(true));
637     assertNotThrown(enforceEx!Exception(true, "blah"));
638     assertNotThrown(enforceEx!OutOfMemoryError(true));
639 
640     {
641         auto e = collectException(enforceEx!Exception(false));
642         assert(e !is null);
643         assert(e.msg.empty);
644         assert(e.file == __FILE__);
645         assert(e.line == __LINE__ - 4);
646     }
647 
648     {
649         auto e = collectException(enforceEx!Exception(false, "hello", "file", 42));
650         assert(e !is null);
651         assert(e.msg == "hello");
652         assert(e.file == "file");
653         assert(e.line == 42);
654     }
655 
656     {
657         auto e = collectException!Error(enforceEx!OutOfMemoryError(false));
658         assert(e !is null);
659         assert(e.msg == "Memory allocation failed");
660         assert(e.file == __FILE__);
661         assert(e.line == __LINE__ - 4);
662     }
663 
664     {
665         auto e = collectException!Error(enforceEx!OutOfMemoryError(false, "file", 42));
666         assert(e !is null);
667         assert(e.msg == "Memory allocation failed");
668         assert(e.file == "file");
669         assert(e.line == 42);
670     }
671 
672     static assert(!is(typeof(enforceEx!int(true))));
673 }
674 
675 @safe unittest
676 {
677     alias enf = enforceEx!Exception;
678     assertNotThrown(enf(true));
679     assertThrown(enf(false, "blah"));
680 }
681 
682 
683 /++
684     Catches and returns the exception thrown from the given expression.
685     If no exception is thrown, then null is returned and $(D result) is
686     set to the result of the expression.
687 
688     Note that while $(D collectException) $(I can) be used to collect any
689     $(D Throwable) and not just $(D Exception)s, it is generally ill-advised to
690     catch anything that is neither an $(D Exception) nor a type derived from
691     $(D Exception). So, do not use $(D collectException) to collect
692     non-$(D Exception)s unless you're sure that that's what you really want to
693     do.
694 
695     Params:
696         T          = The type of exception to catch.
697         expression = The expression which may throw an exception.
698         result     = The result of the expression if no exception is thrown.
699 +/
700 T collectException(T = Exception, E)(lazy E expression, ref E result)
701 {
702     try
703     {
704         result = expression();
705     }
catch(T e)706     catch (T e)
707     {
708         return e;
709     }
710     return null;
711 }
712 ///
713 @system unittest
714 {
715     int b;
foo()716     int foo() { throw new Exception("blah"); }
717     assert(collectException(foo(), b));
718 
719     int[] a = new int[3];
720     import core.exception : RangeError;
721     assert(collectException!RangeError(a[4], b));
722 }
723 
724 /++
725     Catches and returns the exception thrown from the given expression.
726     If no exception is thrown, then null is returned. $(D E) can be
727     $(D void).
728 
729     Note that while $(D collectException) $(I can) be used to collect any
730     $(D Throwable) and not just $(D Exception)s, it is generally ill-advised to
731     catch anything that is neither an $(D Exception) nor a type derived from
732     $(D Exception). So, do not use $(D collectException) to collect
733     non-$(D Exception)s unless you're sure that that's what you really want to
734     do.
735 
736     Params:
737         T          = The type of exception to catch.
738         expression = The expression which may throw an exception.
739 +/
740 T collectException(T : Throwable = Exception, E)(lazy E expression)
741 {
742     try
743     {
744         expression();
745     }
catch(T t)746     catch (T t)
747     {
748         return t;
749     }
750     return null;
751 }
752 
753 @safe unittest
754 {
foo()755     int foo() { throw new Exception("blah"); }
756     assert(collectException(foo()));
757 }
758 
759 /++
760     Catches the exception thrown from the given expression and returns the
761     msg property of that exception. If no exception is thrown, then null is
762     returned. $(D E) can be $(D void).
763 
764     If an exception is thrown but it has an empty message, then
765     $(D emptyExceptionMsg) is returned.
766 
767     Note that while $(D collectExceptionMsg) $(I can) be used to collect any
768     $(D Throwable) and not just $(D Exception)s, it is generally ill-advised to
769     catch anything that is neither an $(D Exception) nor a type derived from
770     $(D Exception). So, do not use $(D collectExceptionMsg) to collect
771     non-$(D Exception)s unless you're sure that that's what you really want to
772     do.
773 
774     Params:
775         T          = The type of exception to catch.
776         expression = The expression which may throw an exception.
777 +/
778 string collectExceptionMsg(T = Exception, E)(lazy E expression)
779 {
780     import std.array : empty;
781     try
782     {
783         expression();
784 
785         return cast(string) null;
786     }
787     catch (T e)
788         return e.msg.empty ? emptyExceptionMsg : e.msg;
789 }
790 ///
791 @safe unittest
792 {
throwFunc()793     void throwFunc() { throw new Exception("My Message."); }
794     assert(collectExceptionMsg(throwFunc()) == "My Message.");
795 
nothrowFunc()796     void nothrowFunc() {}
797     assert(collectExceptionMsg(nothrowFunc()) is null);
798 
throwEmptyFunc()799     void throwEmptyFunc() { throw new Exception(""); }
800     assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg);
801 }
802 
803 /++
804     Value that collectExceptionMsg returns when it catches an exception
805     with an empty exception message.
806  +/
807 enum emptyExceptionMsg = "<Empty Exception Message>";
808 
809 /**
810  * Casts a mutable array to an immutable array in an idiomatic
811  * manner. Technically, $(D assumeUnique) just inserts a cast,
812  * but its name documents assumptions on the part of the
813  * caller. $(D assumeUnique(arr)) should only be called when
814  * there are no more active mutable aliases to elements of $(D
815  * arr). To strengthen this assumption, $(D assumeUnique(arr))
816  * also clears $(D arr) before returning. Essentially $(D
817  * assumeUnique(arr)) indicates commitment from the caller that there
818  * is no more mutable access to any of $(D arr)'s elements
819  * (transitively), and that all future accesses will be done through
820  * the immutable array returned by $(D assumeUnique).
821  *
822  * Typically, $(D assumeUnique) is used to return arrays from
823  * functions that have allocated and built them.
824  *
825  * Params:
826  *  array = The array to cast to immutable.
827  *
828  * Returns: The immutable array.
829  *
830  * Example:
831  *
832  * ----
833  * string letters()
834  * {
835  *   char[] result = new char['z' - 'a' + 1];
836  *   foreach (i, ref e; result)
837  *   {
838  *     e = cast(char)('a' + i);
839  *   }
840  *   return assumeUnique(result);
841  * }
842  * ----
843  *
844  * The use in the example above is correct because $(D result)
845  * was private to $(D letters) and is inaccessible in writing
846  * after the function returns. The following example shows an
847  * incorrect use of $(D assumeUnique).
848  *
849  * Bad:
850  *
851  * ----
852  * private char[] buffer;
853  * string letters(char first, char last)
854  * {
855  *   if (first >= last) return null; // fine
856  *   auto sneaky = buffer;
857  *   sneaky.length = last - first + 1;
858  *   foreach (i, ref e; sneaky)
859  *   {
860  *     e = cast(char)('a' + i);
861  *   }
862  *   return assumeUnique(sneaky); // BAD
863  * }
864  * ----
865  *
866  * The example above wreaks havoc on client code because it is
867  * modifying arrays that callers considered immutable. To obtain an
868  * immutable array from the writable array $(D buffer), replace
869  * the last line with:
870  * ----
871  * return to!(string)(sneaky); // not that sneaky anymore
872  * ----
873  *
874  * The call will duplicate the array appropriately.
875  *
876  * Note that checking for uniqueness during compilation is
877  * possible in certain cases, especially when a function is
878  * marked as a pure function. The following example does not
879  * need to call assumeUnique because the compiler can infer the
880  * uniqueness of the array in the pure function:
881  * ----
882  * string letters() pure
883  * {
884  *   char[] result = new char['z' - 'a' + 1];
885  *   foreach (i, ref e; result)
886  *   {
887  *     e = cast(char)('a' + i);
888  *   }
889  *   return result;
890  * }
891  * ----
892  *
893  * For more on infering uniqueness see the $(B unique) and
894  * $(B lent) keywords in the
895  * $(HTTP archjava.fluid.cs.cmu.edu/papers/oopsla02.pdf, ArchJava)
896  * language.
897  *
898  * The downside of using $(D assumeUnique)'s
899  * convention-based usage is that at this time there is no
900  * formal checking of the correctness of the assumption;
901  * on the upside, the idiomatic use of $(D assumeUnique) is
902  * simple and rare enough to be tolerable.
903  *
904  */
immutable(T)905 immutable(T)[] assumeUnique(T)(T[] array) pure nothrow
906 {
907     return .assumeUnique(array);    // call ref version
908 }
909 /// ditto
immutable(T)910 immutable(T)[] assumeUnique(T)(ref T[] array) pure nothrow
911 {
912     auto result = cast(immutable(T)[]) array;
913     array = null;
914     return result;
915 }
916 /// ditto
assumeUnique(T,U)917 immutable(T[U]) assumeUnique(T, U)(ref T[U] array) pure nothrow
918 {
919     auto result = cast(immutable(T[U])) array;
920     array = null;
921     return result;
922 }
923 
924 @system unittest
925 {
926     // @system due to assumeUnique
927     int[] arr = new int[1];
928     auto arr1 = assumeUnique(arr);
929     assert(is(typeof(arr1) == immutable(int)[]) && arr == null);
930 }
931 
932 // @@@BUG@@@
version(none)933 version (none) @system unittest
934 {
935     int[string] arr = ["a":1];
936     auto arr1 = assumeUnique(arr);
937     assert(is(typeof(arr1) == immutable(int[string])) && arr == null);
938 }
939 
940 /**
941  * Wraps a possibly-throwing expression in a $(D nothrow) wrapper so that it
942  * can be called by a $(D nothrow) function.
943  *
944  * This wrapper function documents commitment on the part of the caller that
945  * the appropriate steps have been taken to avoid whatever conditions may
946  * trigger an exception during the evaluation of $(D expr).  If it turns out
947  * that the expression $(I does) throw at runtime, the wrapper will throw an
948  * $(D AssertError).
949  *
950  * (Note that $(D Throwable) objects such as $(D AssertError) that do not
951  * subclass $(D Exception) may be thrown even from $(D nothrow) functions,
952  * since they are considered to be serious runtime problems that cannot be
953  * recovered from.)
954  *
955  * Params:
956  *  expr = The expression asserted not to throw.
957  *  msg = The message to include in the `AssertError` if the assumption turns
958  *      out to be false.
959  *  file = The source file name of the caller.
960  *  line = The line number of the caller.
961  *
962  * Returns:
963  *  The value of `expr`, if any.
964  */
assumeWontThrow(T)965 T assumeWontThrow(T)(lazy T expr,
966                      string msg = null,
967                      string file = __FILE__,
968                      size_t line = __LINE__) nothrow
969 {
970     import core.exception : AssertError;
971     try
972     {
973         return expr;
974     }
975     catch (Exception e)
976     {
977         import std.range.primitives : empty;
978         immutable tail = msg.empty ? "." : ": " ~ msg;
979         throw new AssertError("assumeWontThrow failed: Expression did throw" ~
980                               tail, file, line);
981     }
982 }
983 
984 ///
985 @safe unittest
986 {
987     import std.math : sqrt;
988 
989     // This function may throw.
squareRoot(int x)990     int squareRoot(int x)
991     {
992         if (x < 0)
993             throw new Exception("Tried to take root of negative number");
994         return cast(int) sqrt(cast(double) x);
995     }
996 
997     // This function never throws.
computeLength(int x,int y)998     int computeLength(int x, int y) nothrow
999     {
1000         // Since x*x + y*y is always positive, we can safely assume squareRoot
1001         // won't throw, and use it to implement this nothrow function. If it
1002         // does throw (e.g., if x*x + y*y overflows a 32-bit value), then the
1003         // program will terminate.
1004         return assumeWontThrow(squareRoot(x*x + y*y));
1005     }
1006 
1007     assert(computeLength(3, 4) == 5);
1008 }
1009 
1010 @system unittest
1011 {
1012     import core.exception : AssertError;
1013 
alwaysThrows()1014     void alwaysThrows()
1015     {
1016         throw new Exception("I threw up");
1017     }
bad()1018     void bad() nothrow
1019     {
1020         assumeWontThrow(alwaysThrows());
1021     }
1022     assertThrown!AssertError(bad());
1023 }
1024 
1025 /**
1026 Checks whether a given source object contains pointers or references to a given
1027 target object.
1028 
1029 Params:
1030     source = The source object
1031     target = The target object
1032 
1033 Returns: $(D true) if $(D source)'s representation embeds a pointer
1034 that points to $(D target)'s representation or somewhere inside
1035 it.
1036 
1037 If $(D source) is or contains a dynamic array, then, then these functions will check
1038 if there is overlap between the dynamic array and $(D target)'s representation.
1039 
1040 If $(D source) is a class, then it will be handled as a pointer.
1041 
1042 If $(D target) is a pointer, a dynamic array or a class, then these functions will only
1043 check if $(D source) points to $(D target), $(I not) what $(D target) references.
1044 
1045 If $(D source) is or contains a union, then there may be either false positives or
1046 false negatives:
1047 
1048 $(D doesPointTo) will return $(D true) if it is absolutely certain
1049 $(D source) points to $(D target). It may produce false negatives, but never
1050 false positives. This function should be prefered when trying to validate
1051 input data.
1052 
1053 $(D mayPointTo) will return $(D false) if it is absolutely certain
1054 $(D source) does not point to $(D target). It may produce false positives, but never
1055 false negatives. This function should be prefered for defensively choosing a
1056 code path.
1057 
1058 Note: Evaluating $(D doesPointTo(x, x)) checks whether $(D x) has
1059 internal pointers. This should only be done as an assertive test,
1060 as the language is free to assume objects don't have internal pointers
1061 (TDPL 7.1.3.5).
1062 */
1063 bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow
1064 if (__traits(isRef, source) || isDynamicArray!S ||
1065     isPointer!S || is(S == class))
1066 {
1067     static if (isPointer!S || is(S == class) || is(S == interface))
1068     {
1069         const m = *cast(void**) &source;
1070         const b = cast(void*) &target;
1071         const e = b + target.sizeof;
1072         return b <= m && m < e;
1073     }
1074     else static if (is(S == struct) || is(S == union))
1075     {
1076         foreach (i, Subobj; typeof(source.tupleof))
1077             static if (!isUnionAliased!(S, i))
1078                 if (doesPointTo(source.tupleof[i], target)) return true;
1079         return false;
1080     }
1081     else static if (isStaticArray!S)
1082     {
1083         foreach (size_t i; 0 .. S.length)
1084             if (doesPointTo(source[i], target)) return true;
1085         return false;
1086     }
1087     else static if (isDynamicArray!S)
1088     {
1089         import std.array : overlap;
1090         return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0;
1091     }
1092     else
1093     {
1094         return false;
1095     }
1096 }
1097 
1098 // for shared objects
1099 /// ditto
doesPointTo(S,T)1100 bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow
1101 {
1102     return doesPointTo!(shared S, shared T, void)(source, target);
1103 }
1104 
1105 /// ditto
1106 bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow
1107 if (__traits(isRef, source) || isDynamicArray!S ||
1108     isPointer!S || is(S == class))
1109 {
1110     static if (isPointer!S || is(S == class) || is(S == interface))
1111     {
1112         const m = *cast(void**) &source;
1113         const b = cast(void*) &target;
1114         const e = b + target.sizeof;
1115         return b <= m && m < e;
1116     }
1117     else static if (is(S == struct) || is(S == union))
1118     {
1119         foreach (i, Subobj; typeof(source.tupleof))
1120             if (mayPointTo(source.tupleof[i], target)) return true;
1121         return false;
1122     }
1123     else static if (isStaticArray!S)
1124     {
1125         foreach (size_t i; 0 .. S.length)
1126             if (mayPointTo(source[i], target)) return true;
1127         return false;
1128     }
1129     else static if (isDynamicArray!S)
1130     {
1131         import std.array : overlap;
1132         return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0;
1133     }
1134     else
1135     {
1136         return false;
1137     }
1138 }
1139 
1140 // for shared objects
1141 /// ditto
mayPointTo(S,T)1142 bool mayPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow
1143 {
1144     return mayPointTo!(shared S, shared T, void)(source, target);
1145 }
1146 
1147 /// Pointers
1148 @system unittest
1149 {
1150     int  i = 0;
1151     int* p = null;
1152     assert(!p.doesPointTo(i));
1153     p = &i;
1154     assert( p.doesPointTo(i));
1155 }
1156 
1157 /// Structs and Unions
1158 @system unittest
1159 {
1160     struct S
1161     {
1162         int v;
1163         int* p;
1164     }
1165     int i;
1166     auto s = S(0, &i);
1167 
1168     // structs and unions "own" their members
1169     // pointsTo will answer true if one of the members pointsTo.
1170     assert(!s.doesPointTo(s.v)); //s.v is just v member of s, so not pointed.
1171     assert( s.p.doesPointTo(i)); //i is pointed by s.p.
1172     assert( s  .doesPointTo(i)); //which means i is pointed by s itself.
1173 
1174     // Unions will behave exactly the same. Points to will check each "member"
1175     // individually, even if they share the same memory
1176 }
1177 
1178 /// Arrays (dynamic and static)
1179 @system unittest
1180 {
1181     int i;
1182     int[]  slice = [0, 1, 2, 3, 4];
1183     int[5] arr   = [0, 1, 2, 3, 4];
1184     int*[]  slicep = [&i];
1185     int*[1] arrp   = [&i];
1186 
1187     // A slice points to all of its members:
1188     assert( slice.doesPointTo(slice[3]));
1189     assert(!slice[0 .. 2].doesPointTo(slice[3])); // Object 3 is outside of the
1190                                                   // slice [0 .. 2]
1191 
1192     // Note that a slice will not take into account what its members point to.
1193     assert( slicep[0].doesPointTo(i));
1194     assert(!slicep   .doesPointTo(i));
1195 
1196     // static arrays are objects that own their members, just like structs:
1197     assert(!arr.doesPointTo(arr[0])); // arr[0] is just a member of arr, so not
1198                                       // pointed.
1199     assert( arrp[0].doesPointTo(i));  // i is pointed by arrp[0].
1200     assert( arrp   .doesPointTo(i));  // which means i is pointed by arrp
1201                                       // itself.
1202 
1203     // Notice the difference between static and dynamic arrays:
1204     assert(!arr  .doesPointTo(arr[0]));
1205     assert( arr[].doesPointTo(arr[0]));
1206     assert( arrp  .doesPointTo(i));
1207     assert(!arrp[].doesPointTo(i));
1208 }
1209 
1210 /// Classes
1211 @system unittest
1212 {
1213     class C
1214     {
this(int * p)1215         this(int* p){this.p = p;}
1216         int* p;
1217     }
1218     int i;
1219     C a = new C(&i);
1220     C b = a;
1221 
1222     // Classes are a bit particular, as they are treated like simple pointers
1223     // to a class payload.
1224     assert( a.p.doesPointTo(i)); // a.p points to i.
1225     assert(!a  .doesPointTo(i)); // Yet a itself does not point i.
1226 
1227     //To check the class payload itself, iterate on its members:
1228     ()
1229     {
1230         import std.traits : Fields;
1231 
1232         foreach (index, _; Fields!C)
1233             if (doesPointTo(a.tupleof[index], i))
1234                 return;
1235         assert(0);
1236     }();
1237 
1238     // To check if a class points a specific payload, a direct memmory check
1239     // can be done:
1240     auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a;
1241     assert(b.doesPointTo(*aLoc)); // b points to where a is pointing
1242 }
1243 
1244 @system unittest
1245 {
1246     struct S1 { int a; S1 * b; }
1247     S1 a1;
1248     S1 * p = &a1;
1249     assert(doesPointTo(p, a1));
1250 
1251     S1 a2;
1252     a2.b = &a1;
1253     assert(doesPointTo(a2, a1));
1254 
1255     struct S3 { int[10] a; }
1256     S3 a3;
1257     auto a4 = a3.a[2 .. 3];
1258     assert(doesPointTo(a4, a3));
1259 
1260     auto a5 = new double[4];
1261     auto a6 = a5[1 .. 2];
1262     assert(!doesPointTo(a5, a6));
1263 
1264     auto a7 = new double[3];
1265     auto a8 = new double[][1];
1266     a8[0] = a7;
1267     assert(!doesPointTo(a8[0], a8[0]));
1268 
1269     // don't invoke postblit on subobjects
1270     {
thisNoCopy1271         static struct NoCopy { this(this) { assert(0); } }
1272         static struct Holder { NoCopy a, b, c; }
1273         Holder h;
1274         cast(void) doesPointTo(h, h);
1275     }
1276 
1277     shared S3 sh3;
1278     shared sh3sub = sh3.a[];
1279     assert(doesPointTo(sh3sub, sh3));
1280 
1281     int[] darr = [1, 2, 3, 4];
1282 
1283     //dynamic arrays don't point to each other, or slices of themselves
1284     assert(!doesPointTo(darr, darr));
1285     assert(!doesPointTo(darr[0 .. 1], darr));
1286 
1287     //But they do point their elements
1288     foreach (i; 0 .. 4)
1289         assert(doesPointTo(darr, darr[i]));
1290     assert(doesPointTo(darr[0 .. 3], darr[2]));
1291     assert(!doesPointTo(darr[0 .. 3], darr[3]));
1292 }
1293 
1294 @system unittest
1295 {
1296     //tests with static arrays
1297     //Static arrays themselves are just objects, and don't really *point* to anything.
1298     //They aggregate their contents, much the same way a structure aggregates its attributes.
1299     //*However* The elements inside the static array may themselves point to stuff.
1300 
1301     //Standard array
1302     int[2] k;
1303     assert(!doesPointTo(k, k)); //an array doesn't point to itself
1304     //Technically, k doesn't point its elements, although it does alias them
1305     assert(!doesPointTo(k, k[0]));
1306     assert(!doesPointTo(k, k[1]));
1307     //But an extracted slice will point to the same array.
1308     assert(doesPointTo(k[], k));
1309     assert(doesPointTo(k[], k[1]));
1310 
1311     //An array of pointers
1312     int*[2] pp;
1313     int a;
1314     int b;
1315     pp[0] = &a;
1316     assert( doesPointTo(pp, a));  //The array contains a pointer to a
1317     assert(!doesPointTo(pp, b));  //The array does NOT contain a pointer to b
1318     assert(!doesPointTo(pp, pp)); //The array does not point itslef
1319 
1320     //A struct containing a static array of pointers
1321     static struct S
1322     {
1323         int*[2] p;
1324     }
1325     S s;
1326     s.p[0] = &a;
1327     assert( doesPointTo(s, a)); //The struct contains an array that points a
1328     assert(!doesPointTo(s, b)); //But doesn't point b
1329     assert(!doesPointTo(s, s)); //The struct doesn't actually point itslef.
1330 
1331     //An array containing structs that have pointers
1332     static struct SS
1333     {
1334         int* p;
1335     }
1336     SS[2] ss = [SS(&a), SS(null)];
1337     assert( doesPointTo(ss, a));  //The array contains a struct that points to a
1338     assert(!doesPointTo(ss, b));  //The array doesn't contains a struct that points to b
1339     assert(!doesPointTo(ss, ss)); //The array doesn't point itself.
1340 }
1341 
1342 
1343 @system unittest //Unions
1344 {
1345     int i;
1346     union U //Named union
1347     {
1348         size_t asInt = 0;
1349         int*   asPointer;
1350     }
1351     struct S
1352     {
1353         union //Anonymous union
1354         {
1355             size_t asInt = 0;
1356             int*   asPointer;
1357         }
1358     }
1359 
1360     U u;
1361     S s;
1362     assert(!doesPointTo(u, i));
1363     assert(!doesPointTo(s, i));
1364     assert(!mayPointTo(u, i));
1365     assert(!mayPointTo(s, i));
1366 
1367     u.asPointer = &i;
1368     s.asPointer = &i;
1369     assert(!doesPointTo(u, i));
1370     assert(!doesPointTo(s, i));
1371     assert( mayPointTo(u, i));
1372     assert( mayPointTo(s, i));
1373 
1374     u.asInt = cast(size_t)&i;
1375     s.asInt = cast(size_t)&i;
1376     assert(!doesPointTo(u, i));
1377     assert(!doesPointTo(s, i));
1378     assert( mayPointTo(u, i));
1379     assert( mayPointTo(s, i));
1380 }
1381 
1382 @system unittest //Classes
1383 {
1384     int i;
1385     static class A
1386     {
1387         int* p;
1388     }
1389     A a = new A, b = a;
1390     assert(!doesPointTo(a, b)); //a does not point to b
1391     a.p = &i;
1392     assert(!doesPointTo(a, i)); //a does not point to i
1393 }
1394 @safe unittest //alias this test
1395 {
1396     static int i;
1397     static int j;
1398     struct S
1399     {
1400         int* p;
1401         @property int* foo(){return &i;}
1402         alias foo this;
1403     }
1404     assert(is(S : int*));
1405     S s = S(&j);
1406     assert(!doesPointTo(s, i));
1407     assert( doesPointTo(s, j));
1408     assert( doesPointTo(cast(int*) s, i));
1409     assert(!doesPointTo(cast(int*) s, j));
1410 }
1411 @safe unittest //more alias this opCast
1412 {
1413     void* p;
1414     class A
1415     {
1416         void* opCast(T)() if (is(T == void*))
1417         {
1418             return p;
1419         }
1420         alias foo = opCast!(void*);
1421         alias foo this;
1422     }
1423     assert(!doesPointTo(A.init, p));
1424     assert(!mayPointTo(A.init, p));
1425 }
1426 
1427 /+
1428 Returns true if the field at index $(D i) in ($D T) shares its address with another field.
1429 
1430 Note: This does not merelly check if the field is a member of an union, but also that
1431 it is not a single child.
1432 +/
1433 package enum isUnionAliased(T, size_t i) = isUnionAliasedImpl!T(T.tupleof[i].offsetof);
1434 private bool isUnionAliasedImpl(T)(size_t offset)
1435 {
1436     int count = 0;
1437     foreach (i, U; typeof(T.tupleof))
1438         if (T.tupleof[i].offsetof == offset)
1439             ++count;
1440     return count >= 2;
1441 }
1442 //
1443 @safe unittest
1444 {
1445     static struct S
1446     {
1447         int a0; //Not aliased
1448         union
1449         {
1450             int a1; //Not aliased
1451         }
1452         union
1453         {
1454             int a2; //Aliased
1455             int a3; //Aliased
1456         }
1457         union A4
1458         {
1459             int b0; //Not aliased
1460         }
1461         A4 a4;
1462         union A5
1463         {
1464             int b0; //Aliased
1465             int b1; //Aliased
1466         }
1467         A5 a5;
1468     }
1469 
1470     static assert(!isUnionAliased!(S, 0)); //a0;
1471     static assert(!isUnionAliased!(S, 1)); //a1;
1472     static assert( isUnionAliased!(S, 2)); //a2;
1473     static assert( isUnionAliased!(S, 3)); //a3;
1474     static assert(!isUnionAliased!(S, 4)); //a4;
1475         static assert(!isUnionAliased!(S.A4, 0)); //a4.b0;
1476     static assert(!isUnionAliased!(S, 5)); //a5;
1477         static assert( isUnionAliased!(S.A5, 0)); //a5.b0;
1478         static assert( isUnionAliased!(S.A5, 1)); //a5.b1;
1479 }
1480 
1481 version (CRuntime_Glibc) version = GNU_STRERROR;
1482 version (CRuntime_UClibc) version = GNU_STRERROR;
1483 
1484 package string errnoString(int errno) nothrow @trusted
1485 {
1486     import core.stdc.string : strlen;
1487     version (GNU_STRERROR)
1488     {
1489         import core.stdc.string : strerror_r;
1490         char[1024] buf = void;
1491         auto s = strerror_r(errno, buf.ptr, buf.length);
1492     }
1493     else version (Posix)
1494     {
1495         // XSI-compliant
1496         import core.stdc.string : strerror_r;
1497         char[1024] buf = void;
1498         const(char)* s;
1499         if (strerror_r(errno, buf.ptr, buf.length) == 0)
1500             s = buf.ptr;
1501         else
1502             return "Unknown error";
1503     }
1504     else
1505     {
1506         import core.stdc.string : strerror;
1507         auto s = strerror(errno);
1508     }
1509     return s[0 .. s.strlen].idup;
1510 }
1511 
1512 /*********************
1513  * Thrown if errors that set $(D errno) occur.
1514  */
1515 class ErrnoException : Exception
1516 {
1517     final @property uint errno() { return _errno; } /// Operating system error code.
1518     private uint _errno;
1519     /// Constructor which takes an error message. The current global $(REF errno, core,stdc,errno) value is used as error code.
1520     this(string msg, string file = null, size_t line = 0) @trusted
1521     {
1522         import core.stdc.errno : errno;
1523         this(msg, errno, file, line);
1524     }
1525     /// Constructor which takes an error message and error code.
1526     this(string msg, int errno, string file = null, size_t line = 0) @trusted
1527     {
1528         _errno = errno;
1529         super(msg ~ " (" ~ errnoString(errno) ~ ")", file, line);
1530     }
1531 
1532     @system unittest
1533     {
1534         import core.stdc.errno : errno, EAGAIN;
1535 
1536         auto old = errno;
1537         scope(exit) errno = old;
1538 
1539         errno = EAGAIN;
1540         auto ex = new ErrnoException("oh no");
1541         assert(ex.errno == EAGAIN);
1542     }
1543 
1544     @system unittest
1545     {
1546         import core.stdc.errno : EAGAIN;
1547         auto ex = new ErrnoException("oh no", EAGAIN);
1548         assert(ex.errno == EAGAIN);
1549     }
1550 }
1551 
1552 /++
1553     ML-style functional exception handling. Runs the supplied expression and
1554     returns its result. If the expression throws a $(D Throwable), runs the
1555     supplied error handler instead and return its result. The error handler's
1556     type must be the same as the expression's type.
1557 
1558     Params:
1559         E            = The type of $(D Throwable)s to catch. Defaults to $(D Exception)
1560         T1           = The type of the expression.
1561         T2           = The return type of the error handler.
1562         expression   = The expression to run and return its result.
1563         errorHandler = The handler to run if the expression throwed.
1564 
1565     Returns:
1566         expression, if it does not throw. Otherwise, returns the result of
1567         errorHandler.
1568 
1569     Example:
1570     --------------------
1571     //Revert to a default value upon an error:
1572     assert("x".to!int().ifThrown(0) == 0);
1573     --------------------
1574 
1575     You can also chain multiple calls to ifThrown, each capturing errors from the
1576     entire preceding expression.
1577 
1578     Example:
1579     --------------------
1580     //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1581     string s="true";
1582     assert(s.to!int().
1583             ifThrown(cast(int) s.to!double()).
1584             ifThrown(cast(int) s.to!bool())
1585             == 1);
1586 
1587     //Respond differently to different types of errors
1588     assert(enforce("x".to!int() < 1).to!string()
1589             .ifThrown!ConvException("not a number")
1590             .ifThrown!Exception("number too small")
1591             == "not a number");
1592     --------------------
1593 
1594     The expression and the errorHandler must have a common type they can both
1595     be implicitly casted to, and that type will be the type of the compound
1596     expression.
1597 
1598     Example:
1599     --------------------
1600     //null and new Object have a common type(Object).
1601     static assert(is(typeof(null.ifThrown(new Object())) == Object));
1602     static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1603 
1604     //1 and new Object do not have a common type.
1605     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1606     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1607     --------------------
1608 
1609     If you need to use the actual thrown exception, you can use a delegate.
1610     Example:
1611     --------------------
1612     //Use a lambda to get the thrown object.
1613     assert("%s".format().ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
1614     --------------------
1615     +/
1616 //lazy version
1617 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler)
1618 {
1619     static assert(!is(typeof(return) == void),
1620         "The error handler's return value("
1621         ~ T2.stringof ~
1622         ") does not have a common type with the expression("
1623         ~ T1.stringof ~
1624         ")."
1625     );
1626     try
1627     {
1628         return expression();
1629     }
1630     catch (E)
1631     {
1632         return errorHandler();
1633     }
1634 }
1635 
1636 ///ditto
1637 //delegate version
1638 CommonType!(T1, T2) ifThrown(E : Throwable, T1, T2)(lazy scope T1 expression, scope T2 delegate(E) errorHandler)
1639 {
1640     static assert(!is(typeof(return) == void),
1641         "The error handler's return value("
1642         ~ T2.stringof ~
1643         ") does not have a common type with the expression("
1644         ~ T1.stringof ~
1645         ")."
1646     );
1647     try
1648     {
1649         return expression();
1650     }
1651     catch (E e)
1652     {
1653         return errorHandler(e);
1654     }
1655 }
1656 
1657 ///ditto
1658 //delegate version, general overload to catch any Exception
1659 CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler)
1660 {
1661     static assert(!is(typeof(return) == void),
1662         "The error handler's return value("
1663         ~ T2.stringof ~
1664         ") does not have a common type with the expression("
1665         ~ T1.stringof ~
1666         ")."
1667     );
1668     try
1669     {
1670         return expression();
1671     }
1672     catch (Exception e)
1673     {
1674         return errorHandler(e);
1675     }
1676 }
1677 
1678 //Verify Examples
1679 @system unittest
1680 {
1681     import std.conv;
1682     import std.string;
1683     //Revert to a default value upon an error:
1684     assert("x".to!int().ifThrown(0) == 0);
1685 
1686     //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1687     string s="true";
1688     assert(s.to!int().
1689             ifThrown(cast(int) s.to!double()).
1690             ifThrown(cast(int) s.to!bool())
1691             == 1);
1692 
1693     //Respond differently to different types of errors
1694     assert(enforce("x".to!int() < 1).to!string()
1695             .ifThrown!ConvException("not a number")
1696             .ifThrown!Exception("number too small")
1697             == "not a number");
1698 
1699     //null and new Object have a common type(Object).
1700     static assert(is(typeof(null.ifThrown(new Object())) == Object));
1701     static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1702 
1703     //1 and new Object do not have a common type.
1704     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1705     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1706 
1707     //Use a lambda to get the thrown object.
1708     assert("%s".format().ifThrown(e => e.classinfo.name) == "std.format.FormatException");
1709 }
1710 
1711 @system unittest
1712 {
1713     import core.exception;
1714     import std.conv;
1715     import std.string;
1716     //Basic behaviour - all versions.
1717     assert("1".to!int().ifThrown(0) == 1);
1718     assert("x".to!int().ifThrown(0) == 0);
1719     assert("1".to!int().ifThrown!ConvException(0) == 1);
1720     assert("x".to!int().ifThrown!ConvException(0) == 0);
1721     assert("1".to!int().ifThrown(e=>0) == 1);
1722     assert("x".to!int().ifThrown(e=>0) == 0);
1723     static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1724     {
1725         assert("1".to!int().ifThrown!ConvException(e=>0) == 1);
1726         assert("x".to!int().ifThrown!ConvException(e=>0) == 0);
1727     }
1728 
1729     //Exceptions other than stated not caught.
1730     assert("x".to!int().ifThrown!StringException(0).collectException!ConvException() !is null);
1731     static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1732     {
1733         assert("x".to!int().ifThrown!StringException(e=>0).collectException!ConvException() !is null);
1734     }
1735 
1736     //Default does not include errors.
1737     int throwRangeError() { throw new RangeError; }
1738     assert(throwRangeError().ifThrown(0).collectException!RangeError() !is null);
1739     assert(throwRangeError().ifThrown(e=>0).collectException!RangeError() !is null);
1740 
1741     //Incompatible types are not accepted.
1742     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1743     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1744     static assert(!__traits(compiles, 1.ifThrown(e=>new Object())));
1745     static assert(!__traits(compiles, (new Object()).ifThrown(e=>1)));
1746 }
1747 
1748 version (unittest) package
1749 @property void assertCTFEable(alias dg)()
1750 {
1751     static assert({ cast(void) dg(); return true; }());
1752     cast(void) dg();
1753 }
1754 
1755 /** This $(D enum) is used to select the primitives of the range to handle by the
1756   $(LREF handle) range wrapper. The values of the $(D enum) can be $(D OR)'d to
1757   select multiple primitives to be handled.
1758 
1759   $(D RangePrimitive.access) is a shortcut for the access primitives; $(D front),
1760   $(D back) and $(D opIndex).
1761 
1762   $(D RangePrimitive.pop) is a shortcut for the mutating primitives;
1763   $(D popFront) and $(D popBack).
1764  */
1765 enum RangePrimitive
1766 {
1767     front    = 0b00_0000_0001, ///
1768     back     = 0b00_0000_0010, /// Ditto
1769     popFront = 0b00_0000_0100, /// Ditto
1770     popBack  = 0b00_0000_1000, /// Ditto
1771     empty    = 0b00_0001_0000, /// Ditto
1772     save     = 0b00_0010_0000, /// Ditto
1773     length   = 0b00_0100_0000, /// Ditto
1774     opDollar = 0b00_1000_0000, /// Ditto
1775     opIndex  = 0b01_0000_0000, /// Ditto
1776     opSlice  = 0b10_0000_0000, /// Ditto
1777     access   = front | back | opIndex, /// Ditto
1778     pop      = popFront | popBack, /// Ditto
1779 }
1780 
1781 /** Handle exceptions thrown from range primitives.
1782 
1783 Use the $(LREF RangePrimitive) enum to specify which primitives to _handle.
1784 Multiple range primitives can be handled at once by using the $(D OR) operator
1785 or the pseudo-primitives $(D RangePrimitive.access) and $(D RangePrimitive.pop).
1786 All handled primitives must have return types or values compatible with the
1787 user-supplied handler.
1788 
1789 Params:
1790     E = The type of $(D Throwable) to _handle.
1791     primitivesToHandle = Set of range primitives to _handle.
1792     handler = The callable that is called when a handled primitive throws a
1793     $(D Throwable) of type $(D E). The handler must accept arguments of
1794     the form $(D E, ref IRange) and its return value is used as the primitive's
1795     return value whenever $(D E) is thrown. For $(D opIndex), the handler can
1796     optionally recieve a third argument; the index that caused the exception.
1797     input = The range to _handle.
1798 
1799 Returns: A wrapper $(D struct) that preserves the range interface of $(D input).
1800 
1801 Note:
1802 Infinite ranges with slicing support must return an instance of
1803 $(REF Take, std,range) when sliced with a specific lower and upper
1804 bound (see $(REF hasSlicing, std,range,primitives)); $(D handle) deals with
1805 this by $(D take)ing 0 from the return value of the handler function and
1806 returning that when an exception is caught.
1807 */
1808 auto handle(E : Throwable, RangePrimitive primitivesToHandle, alias handler, Range)(Range input)
1809 if (isInputRange!Range)
1810 {
1811     static struct Handler
1812     {
1813         private Range range;
1814 
1815         static if (isForwardRange!Range)
1816         {
1817             @property typeof(this) save()
1818             {
1819                 static if (primitivesToHandle & RangePrimitive.save)
1820                 {
1821                     try
1822                     {
1823                         return typeof(this)(range.save);
1824                     }
1825                     catch (E exception)
1826                     {
1827                         return typeof(this)(handler(exception, this.range));
1828                     }
1829                 }
1830                 else
1831                     return typeof(this)(range.save);
1832             }
1833         }
1834 
1835         static if (isInfinite!Range)
1836         {
1837             enum bool empty = false;
1838         }
1839         else
1840         {
1841             @property bool empty()
1842             {
1843                 static if (primitivesToHandle & RangePrimitive.empty)
1844                 {
1845                     try
1846                     {
1847                         return this.range.empty;
1848                     }
1849                     catch (E exception)
1850                     {
1851                         return handler(exception, this.range);
1852                     }
1853                 }
1854                 else
1855                     return this.range.empty;
1856             }
1857         }
1858 
1859         @property auto ref front()
1860         {
1861             static if (primitivesToHandle & RangePrimitive.front)
1862             {
1863                 try
1864                 {
1865                     return this.range.front;
1866                 }
1867                 catch (E exception)
1868                 {
1869                     return handler(exception, this.range);
1870                 }
1871             }
1872             else
1873                 return this.range.front;
1874         }
1875 
1876         void popFront()
1877         {
1878             static if (primitivesToHandle & RangePrimitive.popFront)
1879             {
1880                 try
1881                 {
1882                     this.range.popFront();
1883                 }
1884                 catch (E exception)
1885                 {
1886                     handler(exception, this.range);
1887                 }
1888             }
1889             else
1890                 this.range.popFront();
1891         }
1892 
1893         static if (isBidirectionalRange!Range)
1894         {
1895             @property auto ref back()
1896             {
1897                 static if (primitivesToHandle & RangePrimitive.back)
1898                 {
1899                     try
1900                     {
1901                         return this.range.back;
1902                     }
1903                     catch (E exception)
1904                     {
1905                         return handler(exception, this.range);
1906                     }
1907                 }
1908                 else
1909                     return this.range.back;
1910             }
1911 
1912             void popBack()
1913             {
1914                 static if (primitivesToHandle & RangePrimitive.popBack)
1915                 {
1916                     try
1917                     {
1918                         this.range.popBack();
1919                     }
1920                     catch (E exception)
1921                     {
1922                         handler(exception, this.range);
1923                     }
1924                 }
1925                 else
1926                     this.range.popBack();
1927             }
1928         }
1929 
1930         static if (isRandomAccessRange!Range)
1931         {
1932             auto ref opIndex(size_t index)
1933             {
1934                 static if (primitivesToHandle & RangePrimitive.opIndex)
1935                 {
1936                     try
1937                     {
1938                         return this.range[index];
1939                     }
1940                     catch (E exception)
1941                     {
1942                         static if (__traits(compiles, handler(exception, this.range, index)))
1943                             return handler(exception, this.range, index);
1944                         else
1945                             return handler(exception, this.range);
1946                     }
1947                 }
1948                 else
1949                     return this.range[index];
1950             }
1951         }
1952 
1953         static if (hasLength!Range)
1954         {
1955             @property auto length()
1956             {
1957                 static if (primitivesToHandle & RangePrimitive.length)
1958                 {
1959                     try
1960                     {
1961                         return this.range.length;
1962                     }
1963                     catch (E exception)
1964                     {
1965                         return handler(exception, this.range);
1966                     }
1967                 }
1968                 else
1969                     return this.range.length;
1970             }
1971         }
1972 
1973         static if (hasSlicing!Range)
1974         {
1975             static if (hasLength!Range)
1976             {
1977                 typeof(this) opSlice(size_t lower, size_t upper)
1978                 {
1979                     static if (primitivesToHandle & RangePrimitive.opSlice)
1980                     {
1981                         try
1982                         {
1983                             return typeof(this)(this.range[lower .. upper]);
1984                         }
1985                         catch (E exception)
1986                         {
1987                             return typeof(this)(handler(exception, this.range));
1988                         }
1989                     }
1990                     else
1991                         return typeof(this)(this.range[lower .. upper]);
1992                 }
1993             }
1994             else static if (is(typeof(Range.init[size_t.init .. $])))
1995             {
1996                 import std.range : Take, takeExactly;
1997                 static struct DollarToken {}
1998                 enum opDollar = DollarToken.init;
1999 
2000                 typeof(this) opSlice(size_t lower, DollarToken)
2001                 {
2002                     static if (primitivesToHandle & RangePrimitive.opSlice)
2003                     {
2004                         try
2005                         {
2006                             return typeof(this)(this.range[lower .. $]);
2007                         }
2008                         catch (E exception)
2009                         {
2010                             return typeof(this)(handler(exception, this.range));
2011                         }
2012                     }
2013                     else
2014                         return typeof(this)(this.range[lower .. $]);
2015                 }
2016 
2017                 Take!Handler opSlice(size_t lower, size_t upper)
2018                 {
2019                     static if (primitivesToHandle & RangePrimitive.opSlice)
2020                     {
2021                         try
2022                         {
2023                             return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2024                         }
2025                         catch (E exception)
2026                         {
2027                             return takeExactly(typeof(this)(handler(exception, this.range)), 0);
2028                         }
2029                     }
2030                     else
2031                         return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2032                 }
2033             }
2034         }
2035     }
2036 
2037     return Handler(input);
2038 }
2039 
2040 ///
2041 pure @safe unittest
2042 {
2043     import std.algorithm.comparison : equal;
2044     import std.algorithm.iteration : map, splitter;
2045     import std.conv : to, ConvException;
2046 
2047     auto s = "12,1337z32,54,2,7,9,1z,6,8";
2048 
2049     // The next line composition will throw when iterated
2050     // as some elements of the input do not convert to integer
2051     auto r = s.splitter(',').map!(a => to!int(a));
2052 
2053     // Substitute 0 for cases of ConvException
2054     auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
2055     assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
2056 }
2057 
2058 ///
2059 pure @safe unittest
2060 {
2061     import std.algorithm.comparison : equal;
2062     import std.range : retro;
2063     import std.utf : UTFException;
2064 
2065     auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
2066 
2067     auto handled = str.handle!(UTFException, RangePrimitive.access,
2068             (e, r) => ' '); // Replace invalid code points with spaces
2069 
2070     assert(handled.equal("hello world")); // `front` is handled,
2071     assert(handled.retro.equal("dlrow olleh")); // as well as `back`
2072 }
2073 
2074 pure nothrow @safe unittest
2075 {
2076     static struct ThrowingRange
2077     {
2078         pure @safe:
2079         @property bool empty()
2080         {
2081             throw new Exception("empty has thrown");
2082         }
2083 
2084         @property int front()
2085         {
2086             throw new Exception("front has thrown");
2087         }
2088 
2089         @property int back()
2090         {
2091             throw new Exception("back has thrown");
2092         }
2093 
2094         void popFront()
2095         {
2096             throw new Exception("popFront has thrown");
2097         }
2098 
2099         void popBack()
2100         {
2101             throw new Exception("popBack has thrown");
2102         }
2103 
2104         int opIndex(size_t)
2105         {
2106             throw new Exception("opIndex has thrown");
2107         }
2108 
2109         ThrowingRange opSlice(size_t, size_t)
2110         {
2111             throw new Exception("opSlice has thrown");
2112         }
2113 
2114         @property size_t length()
2115         {
2116             throw new Exception("length has thrown");
2117         }
2118 
2119         alias opDollar = length;
2120 
2121         @property ThrowingRange save()
2122         {
2123             throw new Exception("save has thrown");
2124         }
2125     }
2126 
2127     static assert(isInputRange!ThrowingRange);
2128     static assert(isForwardRange!ThrowingRange);
2129     static assert(isBidirectionalRange!ThrowingRange);
2130     static assert(hasSlicing!ThrowingRange);
2131     static assert(hasLength!ThrowingRange);
2132 
2133     auto f = ThrowingRange();
2134     auto fb = f.handle!(Exception, RangePrimitive.front | RangePrimitive.back,
2135             (e, r) => -1)();
2136     assert(fb.front == -1);
2137     assert(fb.back == -1);
2138     assertThrown(fb.popFront());
2139     assertThrown(fb.popBack());
2140     assertThrown(fb.empty);
2141     assertThrown(fb.save);
2142     assertThrown(fb[0]);
2143 
2144     auto accessRange = f.handle!(Exception, RangePrimitive.access,
2145             (e, r) => -1);
2146     assert(accessRange.front == -1);
2147     assert(accessRange.back == -1);
2148     assert(accessRange[0] == -1);
2149     assertThrown(accessRange.popFront());
2150     assertThrown(accessRange.popBack());
2151 
2152     auto pfb = f.handle!(Exception, RangePrimitive.pop, (e, r) => -1)();
2153 
2154     pfb.popFront(); // this would throw otherwise
2155     pfb.popBack(); // this would throw otherwise
2156 
2157     auto em = f.handle!(Exception,
2158             RangePrimitive.empty, (e, r) => false)();
2159 
2160     assert(!em.empty);
2161 
2162     auto arr = f.handle!(Exception,
2163             RangePrimitive.opIndex, (e, r) => 1337)();
2164 
2165     assert(arr[0] == 1337);
2166 
2167     auto arr2 = f.handle!(Exception,
2168             RangePrimitive.opIndex, (e, r, i) => i)();
2169 
2170     assert(arr2[0] == 0);
2171     assert(arr2[1337] == 1337);
2172 
2173     auto save = f.handle!(Exception,
2174         RangePrimitive.save,
2175         function(Exception e, ref ThrowingRange r) {
2176             return ThrowingRange();
2177         })();
2178 
2179     save.save;
2180 
2181     auto slice = f.handle!(Exception,
2182         RangePrimitive.opSlice, (e, r) => ThrowingRange())();
2183 
2184     auto sliced = slice[0 .. 1337]; // this would throw otherwise
2185 
2186     static struct Infinite
2187     {
2188         import std.range : Take;
2189         pure @safe:
2190         enum bool empty = false;
2191         int front() { assert(false); }
2192         void popFront() { assert(false); }
2193         Infinite save() @property { assert(false); }
2194         static struct DollarToken {}
2195         enum opDollar = DollarToken.init;
2196         Take!Infinite opSlice(size_t, size_t) { assert(false); }
2197         Infinite opSlice(size_t, DollarToken)
2198         {
2199             throw new Exception("opSlice has thrown");
2200         }
2201     }
2202 
2203     static assert(isInputRange!Infinite);
2204     static assert(isInfinite!Infinite);
2205     static assert(hasSlicing!Infinite);
2206 
2207     assertThrown(Infinite()[0 .. $]);
2208 
2209     auto infinite = Infinite.init.handle!(Exception,
2210         RangePrimitive.opSlice, (e, r) => Infinite())();
2211 
2212     auto infSlice = infinite[0 .. $]; // this would throw otherwise
2213 }
2214 
2215 
2216 /++
2217     Convenience mixin for trivially sub-classing exceptions
2218 
2219     Even trivially sub-classing an exception involves writing boilerplate code
2220     for the constructor to: 1$(RPAREN) correctly pass in the source file and line number
2221     the exception was thrown from; 2$(RPAREN) be usable with $(LREF enforce) which
2222     expects exception constructors to take arguments in a fixed order. This
2223     mixin provides that boilerplate code.
2224 
2225     Note however that you need to mark the $(B mixin) line with at least a
2226     minimal (i.e. just $(B ///)) DDoc comment if you want the mixed-in
2227     constructors to be documented in the newly created Exception subclass.
2228 
2229     $(RED Current limitation): Due to
2230     $(LINK2 https://issues.dlang.org/show_bug.cgi?id=11500, bug #11500),
2231     currently the constructors specified in this mixin cannot be overloaded with
2232     any other custom constructors. Thus this mixin can currently only be used
2233     when no such custom constructors need to be explicitly specified.
2234  +/
2235 mixin template basicExceptionCtors()
2236 {
2237     /++
2238         Params:
2239             msg  = The message for the exception.
2240             file = The file where the exception occurred.
2241             line = The line number where the exception occurred.
2242             next = The previous exception in the chain of exceptions, if any.
2243     +/
2244     this(string msg, string file = __FILE__, size_t line = __LINE__,
2245          Throwable next = null) @nogc @safe pure nothrow
2246     {
2247         super(msg, file, line, next);
2248     }
2249 
2250     /++
2251         Params:
2252             msg  = The message for the exception.
2253             next = The previous exception in the chain of exceptions.
2254             file = The file where the exception occurred.
2255             line = The line number where the exception occurred.
2256     +/
2257     this(string msg, Throwable next, string file = __FILE__,
2258          size_t line = __LINE__) @nogc @safe pure nothrow
2259     {
2260         super(msg, file, line, next);
2261     }
2262 }
2263 
2264 ///
2265 @safe unittest
2266 {
2267     class MeaCulpa: Exception
2268     {
2269         ///
2270         mixin basicExceptionCtors;
2271     }
2272 
2273     try
2274         throw new MeaCulpa("test");
2275     catch (MeaCulpa e)
2276     {
2277         assert(e.msg == "test");
2278         assert(e.file == __FILE__);
2279         assert(e.line == __LINE__ - 5);
2280     }
2281 }
2282 
2283 @safe pure nothrow unittest
2284 {
2285     class TestException : Exception { mixin basicExceptionCtors; }
2286     auto e = new Exception("msg");
2287     auto te1 = new TestException("foo");
2288     auto te2 = new TestException("foo", e);
2289 }
2290 
2291 @safe unittest
2292 {
2293     class TestException : Exception { mixin basicExceptionCtors; }
2294     auto e = new Exception("!!!");
2295 
2296     auto te1 = new TestException("message", "file", 42, e);
2297     assert(te1.msg == "message");
2298     assert(te1.file == "file");
2299     assert(te1.line == 42);
2300     assert(te1.next is e);
2301 
2302     auto te2 = new TestException("message", e, "file", 42);
2303     assert(te2.msg == "message");
2304     assert(te2.file == "file");
2305     assert(te2.line == 42);
2306     assert(te2.next is e);
2307 
2308     auto te3 = new TestException("foo");
2309     assert(te3.msg == "foo");
2310     assert(te3.file == __FILE__);
2311     assert(te3.line == __LINE__ - 3);
2312     assert(te3.next is null);
2313 
2314     auto te4 = new TestException("foo", e);
2315     assert(te4.msg == "foo");
2316     assert(te4.file == __FILE__);
2317     assert(te4.line == __LINE__ - 3);
2318     assert(te4.next is e);
2319 }
2320