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