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