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