The OpenD Programming Language

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