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