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 merelly 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     /// Constructor which takes an error message. The current global $(REF errno, core,stdc,errno) value is used as error code.
1636     this(string msg, string file = null, size_t line = 0) @safe
1637     {
1638         import core.stdc.errno : errno;
1639         this(msg, errno, file, line);
1640     }
1641     /// Constructor which takes an error message and error code.
1642     this(string msg, int errno, string file = null, size_t line = 0) @safe
1643     {
1644         _errno = errno;
1645         super(msg ~ " (" ~ errnoString(errno) ~ ")", file, line);
1646     }
1647 }
1648 
1649 ///
1650 @safe unittest
1651 {
1652     import core.stdc.errno : EAGAIN;
1653     auto ex = new ErrnoException("oh no", EAGAIN);
1654     assert(ex.errno == EAGAIN);
1655 }
1656 
1657 /// errno is used by default if no explicit error code is provided
1658 @safe unittest
1659 {
1660     import core.stdc.errno : errno, EAGAIN;
1661 
1662     auto old = errno;
1663     scope(exit) errno = old;
1664 
1665     // fake that errno got set by the callee
1666     errno = EAGAIN;
1667     auto ex = new ErrnoException("oh no");
1668     assert(ex.errno == EAGAIN);
1669 }
1670 
1671 /++
1672     ML-style functional exception handling. Runs the supplied expression and
1673     returns its result. If the expression throws a `Throwable`, runs the
1674     supplied error handler instead and return its result. The error handler's
1675     type must be the same as the expression's type.
1676 
1677     Params:
1678         E            = The type of `Throwable`s to catch. Defaults to `Exception`
1679         T1           = The type of the expression.
1680         T2           = The return type of the error handler.
1681         expression   = The expression to run and return its result.
1682         errorHandler = The handler to run if the expression throwed.
1683 
1684     Returns:
1685         expression, if it does not throw. Otherwise, returns the result of
1686         errorHandler.
1687 +/
1688 //lazy version
1689 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler)
1690 {
1691     static assert(!is(typeof(return) == void),
1692         "The error handler's return value("
1693         ~ T2.stringof ~
1694         ") does not have a common type with the expression("
1695         ~ T1.stringof ~
1696         ")."
1697     );
1698     try
1699     {
1700         return expression();
1701     }
1702     catch (E)
1703     {
1704         return errorHandler();
1705     }
1706 }
1707 
1708 ///ditto
1709 //delegate version
1710 CommonType!(T1, T2) ifThrown(E : Throwable, T1, T2)(lazy scope T1 expression, scope T2 delegate(E) errorHandler)
1711 {
1712     static assert(!is(typeof(return) == void),
1713         "The error handler's return value("
1714         ~ T2.stringof ~
1715         ") does not have a common type with the expression("
1716         ~ T1.stringof ~
1717         ")."
1718     );
1719     try
1720     {
1721         return expression();
1722     }
1723     catch (E e)
1724     {
1725         return errorHandler(e);
1726     }
1727 }
1728 
1729 ///ditto
1730 //delegate version, general overload to catch any Exception
1731 CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler)
1732 {
1733     static assert(!is(typeof(return) == void),
1734         "The error handler's return value("
1735         ~ T2.stringof ~
1736         ") does not have a common type with the expression("
1737         ~ T1.stringof ~
1738         ")."
1739     );
1740     try
1741     {
1742         return expression();
1743     }
1744     catch (Exception e)
1745     {
1746         return errorHandler(e);
1747     }
1748 }
1749 
1750 /// Revert to a default value upon an error:
1751 @safe unittest
1752 {
1753     import std.conv : to;
1754     assert("x".to!int.ifThrown(0) == 0);
1755 }
1756 
1757 /**
1758 Chain multiple calls to ifThrown, each capturing errors from the
1759 entire preceding expression.
1760 */
1761 @safe unittest
1762 {
1763     import std.conv : ConvException, to;
1764     string s = "true";
1765     assert(s.to!int.ifThrown(cast(int) s.to!double)
1766                    .ifThrown(cast(int) s.to!bool) == 1);
1767 
1768     s = "2.0";
1769     assert(s.to!int.ifThrown(cast(int) s.to!double)
1770                    .ifThrown(cast(int) s.to!bool) == 2);
1771 
1772     // Respond differently to different types of errors
1773     alias orFallback = (lazy a)  => a.ifThrown!ConvException("not a number")
1774                                      .ifThrown!Exception("number too small");
1775 
1776     assert(orFallback(enforce("x".to!int < 1).to!string) == "not a number");
1777     assert(orFallback(enforce("2".to!int < 1).to!string) == "number too small");
1778 }
1779 
1780 /**
1781 The expression and the errorHandler must have a common type they can both
1782 be implicitly casted to, and that type will be the type of the compound
1783 expression.
1784 */
1785 @safe unittest
1786 {
1787     // null and new Object have a common type(Object).
1788     static assert(is(typeof(null.ifThrown(new Object())) == Object));
1789     static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1790 
1791     // 1 and new Object do not have a common type.
1792     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1793     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1794 }
1795 
1796 /// Use a lambda to get the thrown object.
1797 @system unittest
1798 {
1799     import std.format : format;
1800     assert("%s".format.ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
1801 }
1802 
1803 //Verify Examples
1804 @system unittest
1805 {
1806     import std.conv;
1807     import std.string;
1808     //Revert to a default value upon an error:
1809     assert("x".to!int().ifThrown(0) == 0);
1810 
1811     //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1812     string s="true";
1813     assert(s.to!int().
1814             ifThrown(cast(int) s.to!double()).
1815             ifThrown(cast(int) s.to!bool())
1816             == 1);
1817 
1818     //Respond differently to different types of errors
1819     assert(enforce("x".to!int() < 1).to!string()
1820             .ifThrown!ConvException("not a number")
1821             .ifThrown!Exception("number too small")
1822             == "not a number");
1823 
1824     //null and new Object have a common type(Object).
1825     static assert(is(typeof(null.ifThrown(new Object())) == Object));
1826     static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1827 
1828     //1 and new Object do not have a common type.
1829     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1830     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1831 
1832     //Use a lambda to get the thrown object.
1833     assert("%s".format().ifThrown(e => e.classinfo.name) == "std.format.FormatException");
1834 }
1835 
1836 @system unittest
1837 {
1838     import core.exception;
1839     import std.conv;
1840     import std.string;
1841     //Basic behaviour - all versions.
1842     assert("1".to!int().ifThrown(0) == 1);
1843     assert("x".to!int().ifThrown(0) == 0);
1844     assert("1".to!int().ifThrown!ConvException(0) == 1);
1845     assert("x".to!int().ifThrown!ConvException(0) == 0);
1846     assert("1".to!int().ifThrown(e=>0) == 1);
1847     assert("x".to!int().ifThrown(e=>0) == 0);
1848     static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1849     {
1850         assert("1".to!int().ifThrown!ConvException(e=>0) == 1);
1851         assert("x".to!int().ifThrown!ConvException(e=>0) == 0);
1852     }
1853 
1854     //Exceptions other than stated not caught.
1855     assert("x".to!int().ifThrown!StringException(0).collectException!ConvException() !is null);
1856     static if (__traits(compiles, 0.ifThrown!Exception(e => 0))) //This will only work with a fix that was not yet pulled
1857     {
1858         assert("x".to!int().ifThrown!StringException(e=>0).collectException!ConvException() !is null);
1859     }
1860 
1861     //Default does not include errors.
1862     int throwRangeError() { throw new RangeError; }
1863     assert(throwRangeError().ifThrown(0).collectException!RangeError() !is null);
1864     assert(throwRangeError().ifThrown(e=>0).collectException!RangeError() !is null);
1865 
1866     //Incompatible types are not accepted.
1867     static assert(!__traits(compiles, 1.ifThrown(new Object())));
1868     static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1869     static assert(!__traits(compiles, 1.ifThrown(e=>new Object())));
1870     static assert(!__traits(compiles, (new Object()).ifThrown(e=>1)));
1871 }
1872 
1873 version (StdUnittest) package
1874 void assertCTFEable(alias dg)()
1875 {
1876     static assert({ cast(void) dg(); return true; }());
1877     cast(void) dg();
1878 }
1879 
1880 /** This `enum` is used to select the primitives of the range to handle by the
1881   $(LREF handle) range wrapper. The values of the `enum` can be `OR`'d to
1882   select multiple primitives to be handled.
1883 
1884   `RangePrimitive.access` is a shortcut for the access primitives; `front`,
1885   `back` and `opIndex`.
1886 
1887   `RangePrimitive.pop` is a shortcut for the mutating primitives;
1888   `popFront` and `popBack`.
1889  */
1890 enum RangePrimitive
1891 {
1892     front    = 0b00_0000_0001, ///
1893     back     = 0b00_0000_0010, /// Ditto
1894     popFront = 0b00_0000_0100, /// Ditto
1895     popBack  = 0b00_0000_1000, /// Ditto
1896     empty    = 0b00_0001_0000, /// Ditto
1897     save     = 0b00_0010_0000, /// Ditto
1898     length   = 0b00_0100_0000, /// Ditto
1899     opDollar = 0b00_1000_0000, /// Ditto
1900     opIndex  = 0b01_0000_0000, /// Ditto
1901     opSlice  = 0b10_0000_0000, /// Ditto
1902     access   = front | back | opIndex, /// Ditto
1903     pop      = popFront | popBack, /// Ditto
1904 }
1905 
1906 ///
1907 pure @safe unittest
1908 {
1909     import std.algorithm.comparison : equal;
1910     import std.algorithm.iteration : map, splitter;
1911     import std.conv : to, ConvException;
1912 
1913     auto s = "12,1337z32,54,2,7,9,1z,6,8";
1914 
1915     // The next line composition will throw when iterated
1916     // as some elements of the input do not convert to integer
1917     auto r = s.splitter(',').map!(a => to!int(a));
1918 
1919     // Substitute 0 for cases of ConvException
1920     auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
1921     assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
1922 }
1923 
1924 ///
1925 pure @safe unittest
1926 {
1927     import std.algorithm.comparison : equal;
1928     import std.range : retro;
1929     import std.utf : UTFException;
1930 
1931     auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
1932 
1933     auto handled = str.handle!(UTFException, RangePrimitive.access,
1934             (e, r) => ' '); // Replace invalid code points with spaces
1935 
1936     assert(handled.equal("hello world")); // `front` is handled,
1937     assert(handled.retro.equal("dlrow olleh")); // as well as `back`
1938 }
1939 
1940 /** Handle exceptions thrown from range primitives.
1941 
1942 Use the $(LREF RangePrimitive) enum to specify which primitives to _handle.
1943 Multiple range primitives can be handled at once by using the `OR` operator
1944 or the pseudo-primitives `RangePrimitive.access` and `RangePrimitive.pop`.
1945 All handled primitives must have return types or values compatible with the
1946 user-supplied handler.
1947 
1948 Params:
1949     E = The type of `Throwable` to _handle.
1950     primitivesToHandle = Set of range primitives to _handle.
1951     handler = The callable that is called when a handled primitive throws a
1952     `Throwable` of type `E`. The handler must accept arguments of
1953     the form $(D E, ref IRange) and its return value is used as the primitive's
1954     return value whenever `E` is thrown. For `opIndex`, the handler can
1955     optionally recieve a third argument; the index that caused the exception.
1956     input = The range to _handle.
1957 
1958 Returns: A wrapper `struct` that preserves the range interface of `input`.
1959 
1960 Note:
1961 Infinite ranges with slicing support must return an instance of
1962 $(REF Take, std,range) when sliced with a specific lower and upper
1963 bound (see $(REF hasSlicing, std,range,primitives)); `handle` deals with
1964 this by `take`ing 0 from the return value of the handler function and
1965 returning that when an exception is caught.
1966 */
1967 auto handle(E : Throwable, RangePrimitive primitivesToHandle, alias handler, Range)(Range input)
1968 if (isInputRange!Range)
1969 {
1970     static struct Handler
1971     {
1972         private Range range;
1973 
1974         static if (isForwardRange!Range)
1975         {
1976             @property typeof(this) save()
1977             {
1978                 static if (primitivesToHandle & RangePrimitive.save)
1979                 {
1980                     try
1981                     {
1982                         return typeof(this)(range.save);
1983                     }
1984                     catch (E exception)
1985                     {
1986                         return typeof(this)(handler(exception, this.range));
1987                     }
1988                 }
1989                 else
1990                     return typeof(this)(range.save);
1991             }
1992         }
1993 
1994         static if (isInfinite!Range)
1995         {
1996             enum bool empty = false;
1997         }
1998         else
1999         {
2000             @property bool empty()
2001             {
2002                 static if (primitivesToHandle & RangePrimitive.empty)
2003                 {
2004                     try
2005                     {
2006                         return this.range.empty;
2007                     }
2008                     catch (E exception)
2009                     {
2010                         return handler(exception, this.range);
2011                     }
2012                 }
2013                 else
2014                     return this.range.empty;
2015             }
2016         }
2017 
2018         @property auto ref front()
2019         {
2020             static if (primitivesToHandle & RangePrimitive.front)
2021             {
2022                 try
2023                 {
2024                     return this.range.front;
2025                 }
2026                 catch (E exception)
2027                 {
2028                     return handler(exception, this.range);
2029                 }
2030             }
2031             else
2032                 return this.range.front;
2033         }
2034 
2035         void popFront()
2036         {
2037             static if (primitivesToHandle & RangePrimitive.popFront)
2038             {
2039                 try
2040                 {
2041                     this.range.popFront();
2042                 }
2043                 catch (E exception)
2044                 {
2045                     handler(exception, this.range);
2046                 }
2047             }
2048             else
2049                 this.range.popFront();
2050         }
2051 
2052         static if (isBidirectionalRange!Range)
2053         {
2054             @property auto ref back()
2055             {
2056                 static if (primitivesToHandle & RangePrimitive.back)
2057                 {
2058                     try
2059                     {
2060                         return this.range.back;
2061                     }
2062                     catch (E exception)
2063                     {
2064                         return handler(exception, this.range);
2065                     }
2066                 }
2067                 else
2068                     return this.range.back;
2069             }
2070 
2071             void popBack()
2072             {
2073                 static if (primitivesToHandle & RangePrimitive.popBack)
2074                 {
2075                     try
2076                     {
2077                         this.range.popBack();
2078                     }
2079                     catch (E exception)
2080                     {
2081                         handler(exception, this.range);
2082                     }
2083                 }
2084                 else
2085                     this.range.popBack();
2086             }
2087         }
2088 
2089         static if (isRandomAccessRange!Range)
2090         {
2091             auto ref opIndex(size_t index)
2092             {
2093                 static if (primitivesToHandle & RangePrimitive.opIndex)
2094                 {
2095                     try
2096                     {
2097                         return this.range[index];
2098                     }
2099                     catch (E exception)
2100                     {
2101                         static if (__traits(compiles, handler(exception, this.range, index)))
2102                             return handler(exception, this.range, index);
2103                         else
2104                             return handler(exception, this.range);
2105                     }
2106                 }
2107                 else
2108                     return this.range[index];
2109             }
2110         }
2111 
2112         static if (hasLength!Range)
2113         {
2114             @property auto length()
2115             {
2116                 static if (primitivesToHandle & RangePrimitive.length)
2117                 {
2118                     try
2119                     {
2120                         return this.range.length;
2121                     }
2122                     catch (E exception)
2123                     {
2124                         return handler(exception, this.range);
2125                     }
2126                 }
2127                 else
2128                     return this.range.length;
2129             }
2130         }
2131 
2132         static if (hasSlicing!Range)
2133         {
2134             static if (hasLength!Range)
2135             {
2136                 typeof(this) opSlice(size_t lower, size_t upper)
2137                 {
2138                     static if (primitivesToHandle & RangePrimitive.opSlice)
2139                     {
2140                         try
2141                         {
2142                             return typeof(this)(this.range[lower .. upper]);
2143                         }
2144                         catch (E exception)
2145                         {
2146                             return typeof(this)(handler(exception, this.range));
2147                         }
2148                     }
2149                     else
2150                         return typeof(this)(this.range[lower .. upper]);
2151                 }
2152             }
2153             else static if (is(typeof(Range.init[size_t.init .. $])))
2154             {
2155                 import std.range : Take, takeExactly;
2156                 static struct DollarToken {}
2157                 enum opDollar = DollarToken.init;
2158 
2159                 typeof(this) opSlice(size_t lower, DollarToken)
2160                 {
2161                     static if (primitivesToHandle & RangePrimitive.opSlice)
2162                     {
2163                         try
2164                         {
2165                             return typeof(this)(this.range[lower .. $]);
2166                         }
2167                         catch (E exception)
2168                         {
2169                             return typeof(this)(handler(exception, this.range));
2170                         }
2171                     }
2172                     else
2173                         return typeof(this)(this.range[lower .. $]);
2174                 }
2175 
2176                 Take!Handler opSlice(size_t lower, size_t upper)
2177                 {
2178                     static if (primitivesToHandle & RangePrimitive.opSlice)
2179                     {
2180                         try
2181                         {
2182                             return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2183                         }
2184                         catch (E exception)
2185                         {
2186                             return takeExactly(typeof(this)(handler(exception, this.range)), 0);
2187                         }
2188                     }
2189                     else
2190                         return takeExactly(typeof(this)(this.range[lower .. $]), upper - 1);
2191                 }
2192             }
2193         }
2194     }
2195 
2196     return Handler(input);
2197 }
2198 
2199 ///
2200 pure @safe unittest
2201 {
2202     import std.algorithm.comparison : equal;
2203     import std.algorithm.iteration : map, splitter;
2204     import std.conv : to, ConvException;
2205 
2206     auto s = "12,1337z32,54,2,7,9,1z,6,8";
2207 
2208     // The next line composition will throw when iterated
2209     // as some elements of the input do not convert to integer
2210     auto r = s.splitter(',').map!(a => to!int(a));
2211 
2212     // Substitute 0 for cases of ConvException
2213     auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
2214     assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
2215 }
2216 
2217 ///
2218 pure @safe unittest
2219 {
2220     import std.algorithm.comparison : equal;
2221     import std.range : retro;
2222     import std.utf : UTFException;
2223 
2224     auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
2225 
2226     auto handled = str.handle!(UTFException, RangePrimitive.access,
2227             (e, r) => ' '); // Replace invalid code points with spaces
2228 
2229     assert(handled.equal("hello world")); // `front` is handled,
2230     assert(handled.retro.equal("dlrow olleh")); // as well as `back`
2231 }
2232 
2233 pure nothrow @safe unittest
2234 {
2235     static struct ThrowingRange
2236     {
2237         pure @safe:
2238         @property bool empty()
2239         {
2240             throw new Exception("empty has thrown");
2241         }
2242 
2243         @property int front()
2244         {
2245             throw new Exception("front has thrown");
2246         }
2247 
2248         @property int back()
2249         {
2250             throw new Exception("back has thrown");
2251         }
2252 
2253         void popFront()
2254         {
2255             throw new Exception("popFront has thrown");
2256         }
2257 
2258         void popBack()
2259         {
2260             throw new Exception("popBack has thrown");
2261         }
2262 
2263         int opIndex(size_t)
2264         {
2265             throw new Exception("opIndex has thrown");
2266         }
2267 
2268         ThrowingRange opSlice(size_t, size_t)
2269         {
2270             throw new Exception("opSlice has thrown");
2271         }
2272 
2273         @property size_t length()
2274         {
2275             throw new Exception("length has thrown");
2276         }
2277 
2278         alias opDollar = length;
2279 
2280         @property ThrowingRange save()
2281         {
2282             throw new Exception("save has thrown");
2283         }
2284     }
2285 
2286     static assert(isInputRange!ThrowingRange);
2287     static assert(isForwardRange!ThrowingRange);
2288     static assert(isBidirectionalRange!ThrowingRange);
2289     static assert(hasSlicing!ThrowingRange);
2290     static assert(hasLength!ThrowingRange);
2291 
2292     auto f = ThrowingRange();
2293     auto fb = f.handle!(Exception, RangePrimitive.front | RangePrimitive.back,
2294             (e, r) => -1)();
2295     assert(fb.front == -1);
2296     assert(fb.back == -1);
2297     assertThrown(fb.popFront());
2298     assertThrown(fb.popBack());
2299     assertThrown(fb.empty);
2300     assertThrown(fb.save);
2301     assertThrown(fb[0]);
2302 
2303     auto accessRange = f.handle!(Exception, RangePrimitive.access,
2304             (e, r) => -1);
2305     assert(accessRange.front == -1);
2306     assert(accessRange.back == -1);
2307     assert(accessRange[0] == -1);
2308     assertThrown(accessRange.popFront());
2309     assertThrown(accessRange.popBack());
2310 
2311     auto pfb = f.handle!(Exception, RangePrimitive.pop, (e, r) => -1)();
2312 
2313     pfb.popFront(); // this would throw otherwise
2314     pfb.popBack(); // this would throw otherwise
2315 
2316     auto em = f.handle!(Exception,
2317             RangePrimitive.empty, (e, r) => false)();
2318 
2319     assert(!em.empty);
2320 
2321     auto arr = f.handle!(Exception,
2322             RangePrimitive.opIndex, (e, r) => 1337)();
2323 
2324     assert(arr[0] == 1337);
2325 
2326     auto arr2 = f.handle!(Exception,
2327             RangePrimitive.opIndex, (e, r, i) => i)();
2328 
2329     assert(arr2[0] == 0);
2330     assert(arr2[1337] == 1337);
2331 
2332     auto save = f.handle!(Exception,
2333         RangePrimitive.save,
2334         function(Exception e, ref ThrowingRange r) {
2335             return ThrowingRange();
2336         })();
2337 
2338     save.save;
2339 
2340     auto slice = f.handle!(Exception,
2341         RangePrimitive.opSlice, (e, r) => ThrowingRange())();
2342 
2343     auto sliced = slice[0 .. 1337]; // this would throw otherwise
2344 
2345     static struct Infinite
2346     {
2347         import std.range : Take;
2348         pure @safe:
2349         enum bool empty = false;
2350         int front() { assert(false); }
2351         void popFront() { assert(false); }
2352         Infinite save() @property { assert(false); }
2353         static struct DollarToken {}
2354         enum opDollar = DollarToken.init;
2355         Take!Infinite opSlice(size_t, size_t) { assert(false); }
2356         Infinite opSlice(size_t, DollarToken)
2357         {
2358             throw new Exception("opSlice has thrown");
2359         }
2360     }
2361 
2362     static assert(isInputRange!Infinite);
2363     static assert(isInfinite!Infinite);
2364     static assert(hasSlicing!Infinite);
2365 
2366     assertThrown(Infinite()[0 .. $]);
2367 
2368     auto infinite = Infinite.init.handle!(Exception,
2369         RangePrimitive.opSlice, (e, r) => Infinite())();
2370 
2371     auto infSlice = infinite[0 .. $]; // this would throw otherwise
2372 }
2373 
2374 
2375 /++
2376     Convenience mixin for trivially sub-classing exceptions
2377 
2378     Even trivially sub-classing an exception involves writing boilerplate code
2379     for the constructor to: 1$(RPAREN) correctly pass in the source file and line number
2380     the exception was thrown from; 2$(RPAREN) be usable with $(LREF enforce) which
2381     expects exception constructors to take arguments in a fixed order. This
2382     mixin provides that boilerplate code.
2383 
2384     Note however that you need to mark the $(B mixin) line with at least a
2385     minimal (i.e. just $(B ///)) DDoc comment if you want the mixed-in
2386     constructors to be documented in the newly created Exception subclass.
2387 
2388     $(RED Current limitation): Due to
2389     $(LINK2 https://issues.dlang.org/show_bug.cgi?id=11500, bug #11500),
2390     currently the constructors specified in this mixin cannot be overloaded with
2391     any other custom constructors. Thus this mixin can currently only be used
2392     when no such custom constructors need to be explicitly specified.
2393  +/
2394 mixin template basicExceptionCtors()
2395 {
2396     /++
2397         Params:
2398             msg  = The message for the exception.
2399             file = The file where the exception occurred.
2400             line = The line number where the exception occurred.
2401             next = The previous exception in the chain of exceptions, if any.
2402     +/
2403     this(string msg, string file = __FILE__, size_t line = __LINE__,
2404          Throwable next = null) @nogc @safe pure nothrow
2405     {
2406         super(msg, file, line, next);
2407     }
2408 
2409     /++
2410         Params:
2411             msg  = The message for the exception.
2412             next = The previous exception in the chain of exceptions.
2413             file = The file where the exception occurred.
2414             line = The line number where the exception occurred.
2415     +/
2416     this(string msg, Throwable next, string file = __FILE__,
2417          size_t line = __LINE__) @nogc @safe pure nothrow
2418     {
2419         super(msg, file, line, next);
2420     }
2421 }
2422 
2423 ///
2424 @safe unittest
2425 {
2426     class MeaCulpa: Exception
2427     {
2428         ///
2429         mixin basicExceptionCtors;
2430     }
2431 
2432     try
2433         throw new MeaCulpa("test");
2434     catch (MeaCulpa e)
2435     {
2436         assert(e.msg == "test");
2437         assert(e.file == __FILE__);
2438         assert(e.line == __LINE__ - 5);
2439     }
2440 }
2441 
2442 @safe pure nothrow unittest
2443 {
2444     class TestException : Exception { mixin basicExceptionCtors; }
2445     auto e = new Exception("msg");
2446     auto te1 = new TestException("foo");
2447     auto te2 = new TestException("foo", e);
2448 }
2449 
2450 @safe unittest
2451 {
2452     class TestException : Exception { mixin basicExceptionCtors; }
2453     auto e = new Exception("!!!");
2454 
2455     auto te1 = new TestException("message", "file", 42, e);
2456     assert(te1.msg == "message");
2457     assert(te1.file == "file");
2458     assert(te1.line == 42);
2459     assert(te1.next is e);
2460 
2461     auto te2 = new TestException("message", e, "file", 42);
2462     assert(te2.msg == "message");
2463     assert(te2.file == "file");
2464     assert(te2.line == 42);
2465     assert(te2.next is e);
2466 
2467     auto te3 = new TestException("foo");
2468     assert(te3.msg == "foo");
2469     assert(te3.file == __FILE__);
2470     assert(te3.line == __LINE__ - 3);
2471     assert(te3.next is null);
2472 
2473     auto te4 = new TestException("foo", e);
2474     assert(te4.msg == "foo");
2475     assert(te4.file == __FILE__);
2476     assert(te4.line == __LINE__ - 3);
2477     assert(te4.next is e);
2478 }