xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/src/std/exception.d (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
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 package string errnoString(int errno) nothrow @trusted
1482 {
1483     import core.stdc.string : strlen;
1484     version (CRuntime_Glibc)
1485     {
1486         import core.stdc.string : strerror_r;
1487         char[1024] buf = void;
1488         auto s = strerror_r(errno, buf.ptr, buf.length);
1489     }
1490     else version (Posix)
1491     {
1492         // XSI-compliant
1493         import core.stdc.string : strerror_r;
1494         char[1024] buf = void;
1495         const(char)* s;
1496         if (strerror_r(errno, buf.ptr, buf.length) == 0)
1497             s = buf.ptr;
1498         else
1499             return "Unknown error";
1500     }
1501     else
1502     {
1503         import core.stdc.string : strerror;
1504         auto s = strerror(errno);
1505     }
1506     return s[0 .. s.strlen].idup;
1507 }
1508 
1509 /*********************
1510  * Thrown if errors that set $(D errno) occur.
1511  */
1512 class ErrnoException : Exception
1513 {
1514     final @property uint errno() { return _errno; } /// Operating system error code.
1515     private uint _errno;
1516     /// Constructor which takes an error message. The current global $(REF errno, core,stdc,errno) value is used as error code.
1517     this(string msg, string file = null, size_t line = 0) @trusted
1518     {
1519         import core.stdc.errno : errno;
1520         this(msg, errno, file, line);
1521     }
1522     /// Constructor which takes an error message and error code.
1523     this(string msg, int errno, string file = null, size_t line = 0) @trusted
1524     {
1525         _errno = errno;
1526         super(msg ~ " (" ~ errnoString(errno) ~ ")", file, line);
1527     }
1528 
1529     @system unittest
1530     {
1531         import core.stdc.errno : errno, EAGAIN;
1532 
1533         auto old = errno;
1534         scope(exit) errno = old;
1535 
1536         errno = EAGAIN;
1537         auto ex = new ErrnoException("oh no");
1538         assert(ex.errno == EAGAIN);
1539     }
1540 
1541     @system unittest
1542     {
1543         import core.stdc.errno : EAGAIN;
1544         auto ex = new ErrnoException("oh no", EAGAIN);
1545         assert(ex.errno == EAGAIN);
1546     }
1547 }
1548 
1549 /++
1550     ML-style functional exception handling. Runs the supplied expression and
1551     returns its result. If the expression throws a $(D Throwable), runs the
1552     supplied error handler instead and return its result. The error handler's
1553     type must be the same as the expression's type.
1554 
1555     Params:
1556         E            = The type of $(D Throwable)s to catch. Defaults to $(D Exception)
1557         T1           = The type of the expression.
1558         T2           = The return type of the error handler.
1559         expression   = The expression to run and return its result.
1560         errorHandler = The handler to run if the expression throwed.
1561 
1562     Returns:
1563         expression, if it does not throw. Otherwise, returns the result of
1564         errorHandler.
1565 
1566     Example:
1567     --------------------
1568     //Revert to a default value upon an error:
1569     assert("x".to!int().ifThrown(0) == 0);
1570     --------------------
1571 
1572     You can also chain multiple calls to ifThrown, each capturing errors from the
1573     entire preceding expression.
1574 
1575     Example:
1576     --------------------
1577     //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1578     string s="true";
1579     assert(s.to!int().
1580             ifThrown(cast(int) s.to!double()).
1581             ifThrown(cast(int) s.to!bool())
1582             == 1);
1583 
1584     //Respond differently to different types of errors
1585     assert(enforce("x".to!int() < 1).to!string()
1586             .ifThrown!ConvException("not a number")
1587             .ifThrown!Exception("number too small")
1588             == "not a number");
1589     --------------------
1590 
1591     The expression and the errorHandler must have a common type they can both
1592     be implicitly casted to, and that type will be the type of the compound
1593     expression.
1594 
1595     Example:
1596     --------------------
1597     //null and new Object have a common type(Object).
1598     static assert(is(typeof(null.ifThrown(new Object())) == Object));
1599     static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1600 
1601     //1 and new Object do not have a common type.
1602     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1603     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1604     --------------------
1605 
1606     If you need to use the actual thrown exception, you can use a delegate.
1607     Example:
1608     --------------------
1609     //Use a lambda to get the thrown object.
1610     assert("%s".format().ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
1611     --------------------
1612     +/
1613 //lazy version
1614 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler)
1615 {
1616     static assert(!is(typeof(return) == void),
1617         "The error handler's return value("
1618         ~ T2.stringof ~
1619         ") does not have a common type with the expression("
1620         ~ T1.stringof ~
1621         ")."
1622     );
1623     try
1624     {
1625         return expression();
1626     }
1627     catch (E)
1628     {
1629         return errorHandler();
1630     }
1631 }
1632 
1633 ///ditto
1634 //delegate version
1635 CommonType!(T1, T2) ifThrown(E : Throwable, T1, T2)(lazy scope T1 expression, scope T2 delegate(E) errorHandler)
1636 {
1637     static assert(!is(typeof(return) == void),
1638         "The error handler's return value("
1639         ~ T2.stringof ~
1640         ") does not have a common type with the expression("
1641         ~ T1.stringof ~
1642         ")."
1643     );
1644     try
1645     {
1646         return expression();
1647     }
1648     catch (E e)
1649     {
1650         return errorHandler(e);
1651     }
1652 }
1653 
1654 ///ditto
1655 //delegate version, general overload to catch any Exception
1656 CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler)
1657 {
1658     static assert(!is(typeof(return) == void),
1659         "The error handler's return value("
1660         ~ T2.stringof ~
1661         ") does not have a common type with the expression("
1662         ~ T1.stringof ~
1663         ")."
1664     );
1665     try
1666     {
1667         return expression();
1668     }
1669     catch (Exception e)
1670     {
1671         return errorHandler(e);
1672     }
1673 }
1674 
1675 //Verify Examples
1676 @system unittest
1677 {
1678     import std.conv;
1679     import std.string;
1680     //Revert to a default value upon an error:
1681     assert("x".to!int().ifThrown(0) == 0);
1682 
1683     //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1684     string s="true";
1685     assert(s.to!int().
1686             ifThrown(cast(int) s.to!double()).
1687             ifThrown(cast(int) s.to!bool())
1688             == 1);
1689 
1690     //Respond differently to different types of errors
1691     assert(enforce("x".to!int() < 1).to!string()
1692             .ifThrown!ConvException("not a number")
1693             .ifThrown!Exception("number too small")
1694             == "not a number");
1695 
1696     //null and new Object have a common type(Object).
1697     static assert(is(typeof(null.ifThrown(new Object())) == Object));
1698     static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1699 
1700     //1 and new Object do not have a common type.
1701     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1702     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1703 
1704     //Use a lambda to get the thrown object.
1705     assert("%s".format().ifThrown(e => e.classinfo.name) == "std.format.FormatException");
1706 }
1707 
1708 @system unittest
1709 {
1710     import core.exception;
1711     import std.conv;
1712     import std.string;
1713     //Basic behaviour - all versions.
1714     assert("1".to!int().ifThrown(0) == 1);
1715     assert("x".to!int().ifThrown(0) == 0);
1716     assert("1".to!int().ifThrown!ConvException(0) == 1);
1717     assert("x".to!int().ifThrown!ConvException(0) == 0);
1718     assert("1".to!int().ifThrown(e=>0) == 1);
1719     assert("x".to!int().ifThrown(e=>0) == 0);
1720     static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1721     {
1722         assert("1".to!int().ifThrown!ConvException(e=>0) == 1);
1723         assert("x".to!int().ifThrown!ConvException(e=>0) == 0);
1724     }
1725 
1726     //Exceptions other than stated not caught.
1727     assert("x".to!int().ifThrown!StringException(0).collectException!ConvException() !is null);
1728     static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1729     {
1730         assert("x".to!int().ifThrown!StringException(e=>0).collectException!ConvException() !is null);
1731     }
1732 
1733     //Default does not include errors.
1734     int throwRangeError() { throw new RangeError; }
1735     assert(throwRangeError().ifThrown(0).collectException!RangeError() !is null);
1736     assert(throwRangeError().ifThrown(e=>0).collectException!RangeError() !is null);
1737 
1738     //Incompatible types are not accepted.
1739     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1740     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1741     static assert(!__traits(compiles, 1.ifThrown(e=>new Object())));
1742     static assert(!__traits(compiles, (new Object()).ifThrown(e=>1)));
1743 }
1744 
1745 version (unittest) package
1746 @property void assertCTFEable(alias dg)()
1747 {
1748     static assert({ cast(void) dg(); return true; }());
1749     cast(void) dg();
1750 }
1751 
1752 /** This $(D enum) is used to select the primitives of the range to handle by the
1753   $(LREF handle) range wrapper. The values of the $(D enum) can be $(D OR)'d to
1754   select multiple primitives to be handled.
1755 
1756   $(D RangePrimitive.access) is a shortcut for the access primitives; $(D front),
1757   $(D back) and $(D opIndex).
1758 
1759   $(D RangePrimitive.pop) is a shortcut for the mutating primitives;
1760   $(D popFront) and $(D popBack).
1761  */
1762 enum RangePrimitive
1763 {
1764     front    = 0b00_0000_0001, ///
1765     back     = 0b00_0000_0010, /// Ditto
1766     popFront = 0b00_0000_0100, /// Ditto
1767     popBack  = 0b00_0000_1000, /// Ditto
1768     empty    = 0b00_0001_0000, /// Ditto
1769     save     = 0b00_0010_0000, /// Ditto
1770     length   = 0b00_0100_0000, /// Ditto
1771     opDollar = 0b00_1000_0000, /// Ditto
1772     opIndex  = 0b01_0000_0000, /// Ditto
1773     opSlice  = 0b10_0000_0000, /// Ditto
1774     access   = front | back | opIndex, /// Ditto
1775     pop      = popFront | popBack, /// Ditto
1776 }
1777 
1778 /** Handle exceptions thrown from range primitives.
1779 
1780 Use the $(LREF RangePrimitive) enum to specify which primitives to _handle.
1781 Multiple range primitives can be handled at once by using the $(D OR) operator
1782 or the pseudo-primitives $(D RangePrimitive.access) and $(D RangePrimitive.pop).
1783 All handled primitives must have return types or values compatible with the
1784 user-supplied handler.
1785 
1786 Params:
1787     E = The type of $(D Throwable) to _handle.
1788     primitivesToHandle = Set of range primitives to _handle.
1789     handler = The callable that is called when a handled primitive throws a
1790     $(D Throwable) of type $(D E). The handler must accept arguments of
1791     the form $(D E, ref IRange) and its return value is used as the primitive's
1792     return value whenever $(D E) is thrown. For $(D opIndex), the handler can
1793     optionally recieve a third argument; the index that caused the exception.
1794     input = The range to _handle.
1795 
1796 Returns: A wrapper $(D struct) that preserves the range interface of $(D input).
1797 
1798 Note:
1799 Infinite ranges with slicing support must return an instance of
1800 $(REF Take, std,range) when sliced with a specific lower and upper
1801 bound (see $(REF hasSlicing, std,range,primitives)); $(D handle) deals with
1802 this by $(D take)ing 0 from the return value of the handler function and
1803 returning that when an exception is caught.
1804 */
1805 auto handle(E : Throwable, RangePrimitive primitivesToHandle, alias handler, Range)(Range input)
1806 if (isInputRange!Range)
1807 {
1808     static struct Handler
1809     {
1810         private Range range;
1811 
1812         static if (isForwardRange!Range)
1813         {
1814             @property typeof(this) save()
1815             {
1816                 static if (primitivesToHandle & RangePrimitive.save)
1817                 {
1818                     try
1819                     {
1820                         return typeof(this)(range.save);
1821                     }
1822                     catch (E exception)
1823                     {
1824                         return typeof(this)(handler(exception, this.range));
1825                     }
1826                 }
1827                 else
1828                     return typeof(this)(range.save);
1829             }
1830         }
1831 
1832         static if (isInfinite!Range)
1833         {
1834             enum bool empty = false;
1835         }
1836         else
1837         {
1838             @property bool empty()
1839             {
1840                 static if (primitivesToHandle & RangePrimitive.empty)
1841                 {
1842                     try
1843                     {
1844                         return this.range.empty;
1845                     }
1846                     catch (E exception)
1847                     {
1848                         return handler(exception, this.range);
1849                     }
1850                 }
1851                 else
1852                     return this.range.empty;
1853             }
1854         }
1855 
1856         @property auto ref front()
1857         {
1858             static if (primitivesToHandle & RangePrimitive.front)
1859             {
1860                 try
1861                 {
1862                     return this.range.front;
1863                 }
1864                 catch (E exception)
1865                 {
1866                     return handler(exception, this.range);
1867                 }
1868             }
1869             else
1870                 return this.range.front;
1871         }
1872 
1873         void popFront()
1874         {
1875             static if (primitivesToHandle & RangePrimitive.popFront)
1876             {
1877                 try
1878                 {
1879                     this.range.popFront();
1880                 }
1881                 catch (E exception)
1882                 {
1883                     handler(exception, this.range);
1884                 }
1885             }
1886             else
1887                 this.range.popFront();
1888         }
1889 
1890         static if (isBidirectionalRange!Range)
1891         {
1892             @property auto ref back()
1893             {
1894                 static if (primitivesToHandle & RangePrimitive.back)
1895                 {
1896                     try
1897                     {
1898                         return this.range.back;
1899                     }
1900                     catch (E exception)
1901                     {
1902                         return handler(exception, this.range);
1903                     }
1904                 }
1905                 else
1906                     return this.range.back;
1907             }
1908 
1909             void popBack()
1910             {
1911                 static if (primitivesToHandle & RangePrimitive.popBack)
1912                 {
1913                     try
1914                     {
1915                         this.range.popBack();
1916                     }
1917                     catch (E exception)
1918                     {
1919                         handler(exception, this.range);
1920                     }
1921                 }
1922                 else
1923                     this.range.popBack();
1924             }
1925         }
1926 
1927         static if (isRandomAccessRange!Range)
1928         {
1929             auto ref opIndex(size_t index)
1930             {
1931                 static if (primitivesToHandle & RangePrimitive.opIndex)
1932                 {
1933                     try
1934                     {
1935                         return this.range[index];
1936                     }
1937                     catch (E exception)
1938                     {
1939                         static if (__traits(compiles, handler(exception, this.range, index)))
1940                             return handler(exception, this.range, index);
1941                         else
1942                             return handler(exception, this.range);
1943                     }
1944                 }
1945                 else
1946                     return this.range[index];
1947             }
1948         }
1949 
1950         static if (hasLength!Range)
1951         {
1952             @property auto length()
1953             {
1954                 static if (primitivesToHandle & RangePrimitive.length)
1955                 {
1956                     try
1957                     {
1958                         return this.range.length;
1959                     }
1960                     catch (E exception)
1961                     {
1962                         return handler(exception, this.range);
1963                     }
1964                 }
1965                 else
1966                     return this.range.length;
1967             }
1968         }
1969 
1970         static if (hasSlicing!Range)
1971         {
1972             static if (hasLength!Range)
1973             {
1974                 typeof(this) opSlice(size_t lower, size_t upper)
1975                 {
1976                     static if (primitivesToHandle & RangePrimitive.opSlice)
1977                     {
1978                         try
1979                         {
1980                             return typeof(this)(this.range[lower .. upper]);
1981                         }
1982                         catch (E exception)
1983                         {
1984                             return typeof(this)(handler(exception, this.range));
1985                         }
1986                     }
1987                     else
1988                         return typeof(this)(this.range[lower .. upper]);
1989                 }
1990             }
1991             else static if (is(typeof(Range.init[size_t.init .. $])))
1992             {
1993                 import std.range : Take, takeExactly;
1994                 static struct DollarToken {}
1995                 enum opDollar = DollarToken.init;
1996 
1997                 typeof(this) opSlice(size_t lower, DollarToken)
1998                 {
1999                     static if (primitivesToHandle & RangePrimitive.opSlice)
2000                     {
2001                         try
2002                         {
2003                             return typeof(this)(this.range[lower .. $]);
2004                         }
2005                         catch (E exception)
2006                         {
2007                             return typeof(this)(handler(exception, this.range));
2008                         }
2009                     }
2010                     else
2011                         return typeof(this)(this.range[lower .. $]);
2012                 }
2013 
2014                 Take!Handler opSlice(size_t lower, size_t upper)
2015                 {
2016                     static if (primitivesToHandle & RangePrimitive.opSlice)
2017                     {
2018                         try
2019                         {
2020                             return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2021                         }
2022                         catch (E exception)
2023                         {
2024                             return takeExactly(typeof(this)(handler(exception, this.range)), 0);
2025                         }
2026                     }
2027                     else
2028                         return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2029                 }
2030             }
2031         }
2032     }
2033 
2034     return Handler(input);
2035 }
2036 
2037 ///
2038 pure @safe unittest
2039 {
2040     import std.algorithm.comparison : equal;
2041     import std.algorithm.iteration : map, splitter;
2042     import std.conv : to, ConvException;
2043 
2044     auto s = "12,1337z32,54,2,7,9,1z,6,8";
2045 
2046     // The next line composition will throw when iterated
2047     // as some elements of the input do not convert to integer
2048     auto r = s.splitter(',').map!(a => to!int(a));
2049 
2050     // Substitute 0 for cases of ConvException
2051     auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
2052     assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
2053 }
2054 
2055 ///
2056 pure @safe unittest
2057 {
2058     import std.algorithm.comparison : equal;
2059     import std.range : retro;
2060     import std.utf : UTFException;
2061 
2062     auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
2063 
2064     auto handled = str.handle!(UTFException, RangePrimitive.access,
2065             (e, r) => ' '); // Replace invalid code points with spaces
2066 
2067     assert(handled.equal("hello world")); // `front` is handled,
2068     assert(handled.retro.equal("dlrow olleh")); // as well as `back`
2069 }
2070 
2071 pure nothrow @safe unittest
2072 {
2073     static struct ThrowingRange
2074     {
2075         pure @safe:
2076         @property bool empty()
2077         {
2078             throw new Exception("empty has thrown");
2079         }
2080 
2081         @property int front()
2082         {
2083             throw new Exception("front has thrown");
2084         }
2085 
2086         @property int back()
2087         {
2088             throw new Exception("back has thrown");
2089         }
2090 
2091         void popFront()
2092         {
2093             throw new Exception("popFront has thrown");
2094         }
2095 
2096         void popBack()
2097         {
2098             throw new Exception("popBack has thrown");
2099         }
2100 
2101         int opIndex(size_t)
2102         {
2103             throw new Exception("opIndex has thrown");
2104         }
2105 
2106         ThrowingRange opSlice(size_t, size_t)
2107         {
2108             throw new Exception("opSlice has thrown");
2109         }
2110 
2111         @property size_t length()
2112         {
2113             throw new Exception("length has thrown");
2114         }
2115 
2116         alias opDollar = length;
2117 
2118         @property ThrowingRange save()
2119         {
2120             throw new Exception("save has thrown");
2121         }
2122     }
2123 
2124     static assert(isInputRange!ThrowingRange);
2125     static assert(isForwardRange!ThrowingRange);
2126     static assert(isBidirectionalRange!ThrowingRange);
2127     static assert(hasSlicing!ThrowingRange);
2128     static assert(hasLength!ThrowingRange);
2129 
2130     auto f = ThrowingRange();
2131     auto fb = f.handle!(Exception, RangePrimitive.front | RangePrimitive.back,
2132             (e, r) => -1)();
2133     assert(fb.front == -1);
2134     assert(fb.back == -1);
2135     assertThrown(fb.popFront());
2136     assertThrown(fb.popBack());
2137     assertThrown(fb.empty);
2138     assertThrown(fb.save);
2139     assertThrown(fb[0]);
2140 
2141     auto accessRange = f.handle!(Exception, RangePrimitive.access,
2142             (e, r) => -1);
2143     assert(accessRange.front == -1);
2144     assert(accessRange.back == -1);
2145     assert(accessRange[0] == -1);
2146     assertThrown(accessRange.popFront());
2147     assertThrown(accessRange.popBack());
2148 
2149     auto pfb = f.handle!(Exception, RangePrimitive.pop, (e, r) => -1)();
2150 
2151     pfb.popFront(); // this would throw otherwise
2152     pfb.popBack(); // this would throw otherwise
2153 
2154     auto em = f.handle!(Exception,
2155             RangePrimitive.empty, (e, r) => false)();
2156 
2157     assert(!em.empty);
2158 
2159     auto arr = f.handle!(Exception,
2160             RangePrimitive.opIndex, (e, r) => 1337)();
2161 
2162     assert(arr[0] == 1337);
2163 
2164     auto arr2 = f.handle!(Exception,
2165             RangePrimitive.opIndex, (e, r, i) => i)();
2166 
2167     assert(arr2[0] == 0);
2168     assert(arr2[1337] == 1337);
2169 
2170     auto save = f.handle!(Exception,
2171         RangePrimitive.save,
2172         function(Exception e, ref ThrowingRange r) {
2173             return ThrowingRange();
2174         })();
2175 
2176     save.save;
2177 
2178     auto slice = f.handle!(Exception,
2179         RangePrimitive.opSlice, (e, r) => ThrowingRange())();
2180 
2181     auto sliced = slice[0 .. 1337]; // this would throw otherwise
2182 
2183     static struct Infinite
2184     {
2185         import std.range : Take;
2186         pure @safe:
2187         enum bool empty = false;
2188         int front() { assert(false); }
2189         void popFront() { assert(false); }
2190         Infinite save() @property { assert(false); }
2191         static struct DollarToken {}
2192         enum opDollar = DollarToken.init;
2193         Take!Infinite opSlice(size_t, size_t) { assert(false); }
2194         Infinite opSlice(size_t, DollarToken)
2195         {
2196             throw new Exception("opSlice has thrown");
2197         }
2198     }
2199 
2200     static assert(isInputRange!Infinite);
2201     static assert(isInfinite!Infinite);
2202     static assert(hasSlicing!Infinite);
2203 
2204     assertThrown(Infinite()[0 .. $]);
2205 
2206     auto infinite = Infinite.init.handle!(Exception,
2207         RangePrimitive.opSlice, (e, r) => Infinite())();
2208 
2209     auto infSlice = infinite[0 .. $]; // this would throw otherwise
2210 }
2211 
2212 
2213 /++
2214     Convenience mixin for trivially sub-classing exceptions
2215 
2216     Even trivially sub-classing an exception involves writing boilerplate code
2217     for the constructor to: 1$(RPAREN) correctly pass in the source file and line number
2218     the exception was thrown from; 2$(RPAREN) be usable with $(LREF enforce) which
2219     expects exception constructors to take arguments in a fixed order. This
2220     mixin provides that boilerplate code.
2221 
2222     Note however that you need to mark the $(B mixin) line with at least a
2223     minimal (i.e. just $(B ///)) DDoc comment if you want the mixed-in
2224     constructors to be documented in the newly created Exception subclass.
2225 
2226     $(RED Current limitation): Due to
2227     $(LINK2 https://issues.dlang.org/show_bug.cgi?id=11500, bug #11500),
2228     currently the constructors specified in this mixin cannot be overloaded with
2229     any other custom constructors. Thus this mixin can currently only be used
2230     when no such custom constructors need to be explicitly specified.
2231  +/
2232 mixin template basicExceptionCtors()
2233 {
2234     /++
2235         Params:
2236             msg  = The message for the exception.
2237             file = The file where the exception occurred.
2238             line = The line number where the exception occurred.
2239             next = The previous exception in the chain of exceptions, if any.
2240     +/
2241     this(string msg, string file = __FILE__, size_t line = __LINE__,
2242          Throwable next = null) @nogc @safe pure nothrow
2243     {
2244         super(msg, file, line, next);
2245     }
2246 
2247     /++
2248         Params:
2249             msg  = The message for the exception.
2250             next = The previous exception in the chain of exceptions.
2251             file = The file where the exception occurred.
2252             line = The line number where the exception occurred.
2253     +/
2254     this(string msg, Throwable next, string file = __FILE__,
2255          size_t line = __LINE__) @nogc @safe pure nothrow
2256     {
2257         super(msg, file, line, next);
2258     }
2259 }
2260 
2261 ///
2262 @safe unittest
2263 {
2264     class MeaCulpa: Exception
2265     {
2266         ///
2267         mixin basicExceptionCtors;
2268     }
2269 
2270     try
2271         throw new MeaCulpa("test");
2272     catch (MeaCulpa e)
2273     {
2274         assert(e.msg == "test");
2275         assert(e.file == __FILE__);
2276         assert(e.line == __LINE__ - 5);
2277     }
2278 }
2279 
2280 @safe pure nothrow unittest
2281 {
2282     class TestException : Exception { mixin basicExceptionCtors; }
2283     auto e = new Exception("msg");
2284     auto te1 = new TestException("foo");
2285     auto te2 = new TestException("foo", e);
2286 }
2287 
2288 @safe unittest
2289 {
2290     class TestException : Exception { mixin basicExceptionCtors; }
2291     auto e = new Exception("!!!");
2292 
2293     auto te1 = new TestException("message", "file", 42, e);
2294     assert(te1.msg == "message");
2295     assert(te1.file == "file");
2296     assert(te1.line == 42);
2297     assert(te1.next is e);
2298 
2299     auto te2 = new TestException("message", e, "file", 42);
2300     assert(te2.msg == "message");
2301     assert(te2.file == "file");
2302     assert(te2.line == 42);
2303     assert(te2.next is e);
2304 
2305     auto te3 = new TestException("foo");
2306     assert(te3.msg == "foo");
2307     assert(te3.file == __FILE__);
2308     assert(te3.line == __LINE__ - 3);
2309     assert(te3.next is null);
2310 
2311     auto te4 = new TestException("foo", e);
2312     assert(te4.msg == "foo");
2313     assert(te4.file == __FILE__);
2314     assert(te4.line == __LINE__ - 3);
2315     assert(te4.next is e);
2316 }
2317