Skip to content

Commit afa7d58

Browse files
authored
Merge pull request #6080 from wilzbach/fix-18319
Fix Issue 18319 - std.exception: enforce example does not compile
2 parents 7823e11 + f4ccf68 commit afa7d58

File tree

1 file changed

+65
-69
lines changed

1 file changed

+65
-69
lines changed

std/exception.d

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -355,31 +355,36 @@ void assertThrown(T : Throwable = Exception, E)
355355

356356
/++
357357
Enforces that the given value is true.
358+
If the given value is false, an exception is thrown.
359+
The
360+
$(UL
361+
$(LI `msg` - error message as a `string`)
362+
$(LI `dg` - custom delegate that return a string and is only called if an exception occurred)
363+
$(LI `ex` - custom exception to be thrown. It is `lazy` and is only created if an exception occurred)
364+
)
358365
359366
Params:
360367
value = The value to test.
361-
E = Exception type to throw if the value evalues to false.
368+
E = Exception type to throw if the value evaluates to false.
362369
msg = The error message to put in the exception if it is thrown.
370+
dg = The delegate to be called if the value evaluates to false.
371+
ex = The exception to throw if the value evaluates to false.
363372
file = The source file of the caller.
364373
line = The line number of the caller.
365374
366-
Returns: $(D value), if `cast(bool) value` is true. Otherwise,
367-
$(D new Exception(msg)) is thrown.
375+
Returns: `value`, if `cast(bool) value` is true. Otherwise,
376+
depending on the chosen overload, `new Exception(msg)`, `dg()` or `ex` is thrown.
368377
369378
Note:
370-
$(D enforce) is used to throw exceptions and is therefore intended to
379+
`enforce` is used to throw exceptions and is therefore intended to
371380
aid in error handling. It is $(I not) intended for verifying the logic
372381
of your program. That is what $(D assert) is for. Also, do not use
373-
$(D enforce) inside of contracts (i.e. inside of $(D in) and $(D out)
382+
`enforce` inside of contracts (i.e. inside of `in` and `out`
374383
blocks and $(D invariant)s), because contracts are compiled out when
375384
compiling with $(I -release).
376385
377-
Example:
378-
--------------------
379-
auto f = enforce(fopen("data.txt"));
380-
auto line = readln(f);
381-
enforce(line.length, "Expected a non-empty line.");
382-
--------------------
386+
If a delegate is passed, the safety and purity of this function are inferred
387+
from `Dg`'s safety and purity.
383388
+/
384389
T enforce(E : Throwable = Exception, T)(T value, lazy const(char)[] msg = null,
385390
string file = __FILE__, size_t line = __LINE__)
@@ -389,21 +394,7 @@ if (is(typeof({ if (!value) {} })))
389394
return value;
390395
}
391396

392-
/++
393-
Enforces that the given value is true.
394-
395-
Params:
396-
value = The value to test.
397-
dg = The delegate to be called if the value evaluates to false.
398-
file = The source file of the caller.
399-
line = The line number of the caller.
400-
401-
Returns: $(D value), if `cast(bool) value` is true. Otherwise, the given
402-
delegate is called.
403-
404-
The safety and purity of this function are inferred from $(D Dg)'s safety
405-
and purity.
406-
+/
397+
/// ditto
407398
T enforce(T, Dg, string file = __FILE__, size_t line = __LINE__)
408399
(T value, scope Dg dg)
409400
if (isSomeFunction!Dg && is(typeof( dg() )) &&
@@ -413,23 +404,40 @@ if (isSomeFunction!Dg && is(typeof( dg() )) &&
413404
return value;
414405
}
415406

416-
private void bailOut(E : Throwable = Exception)(string file, size_t line, in char[] msg)
407+
/// ditto
408+
T enforce(T)(T value, lazy Throwable ex)
417409
{
418-
static if (is(typeof(new E(string.init, string.init, size_t.init))))
419-
{
420-
throw new E(msg ? msg.idup : "Enforcement failed", file, line);
421-
}
422-
else static if (is(typeof(new E(string.init, size_t.init))))
423-
{
424-
throw new E(file, line);
425-
}
426-
else
427-
{
428-
static assert(0, "Expected this(string, string, size_t) or this(string, size_t)" ~
429-
" constructor for " ~ __traits(identifier, E));
430-
}
410+
if (!value) throw ex();
411+
return value;
412+
}
413+
414+
///
415+
unittest
416+
{
417+
import core.stdc.stdlib : malloc, free;
418+
import std.conv : ConvException, to;
419+
420+
// use enforce like assert
421+
int a = 3;
422+
enforce(a > 2, "a needs to be higher than 2.");
423+
424+
// enforce can throw a custom exception
425+
enforce!ConvException(a > 2, "a needs to be higher than 2.");
426+
427+
// enforce will return it's input
428+
enum size = 42;
429+
auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
430+
scope(exit) free(memory.ptr);
431+
}
432+
433+
///
434+
@safe unittest
435+
{
436+
assertNotThrown(enforce(true, new Exception("this should not be thrown")));
437+
assertThrown(enforce(false, new Exception("this should be thrown")));
431438
}
432439

440+
///
433441
@safe unittest
434442
{
435443
assert(enforce(123) == 123);
@@ -447,6 +455,23 @@ private void bailOut(E : Throwable = Exception)(string file, size_t line, in cha
447455
}
448456
}
449457

458+
private void bailOut(E : Throwable = Exception)(string file, size_t line, in char[] msg)
459+
{
460+
static if (is(typeof(new E(string.init, string.init, size_t.init))))
461+
{
462+
throw new E(msg ? msg.idup : "Enforcement failed", file, line);
463+
}
464+
else static if (is(typeof(new E(string.init, size_t.init))))
465+
{
466+
throw new E(file, line);
467+
}
468+
else
469+
{
470+
static assert(0, "Expected this(string, string, size_t) or this(string, size_t)" ~
471+
" constructor for " ~ __traits(identifier, E));
472+
}
473+
}
474+
450475
@safe unittest
451476
{
452477
// Issue 10510
@@ -532,35 +557,6 @@ private void bailOut(E : Throwable = Exception)(string file, size_t line, in cha
532557
static assert(!__traits(compiles, { enforce!E(false); }));
533558
}
534559

535-
/++
536-
Enforces that the given value is true.
537-
538-
Params:
539-
value = The value to test.
540-
ex = The exception to throw if the value evaluates to false.
541-
542-
Returns: $(D value), if `cast(bool) value` is true. Otherwise, $(D ex) is
543-
thrown.
544-
545-
Example:
546-
--------------------
547-
auto f = enforce(fopen("data.txt"));
548-
auto line = readln(f);
549-
enforce(line.length, new IOException); // expect a non-empty line
550-
--------------------
551-
+/
552-
T enforce(T)(T value, lazy Throwable ex)
553-
{
554-
if (!value) throw ex();
555-
return value;
556-
}
557-
558-
@safe unittest
559-
{
560-
assertNotThrown(enforce(true, new Exception("this should not be thrown")));
561-
assertThrown(enforce(false, new Exception("this should be thrown")));
562-
}
563-
564560
/++
565561
Enforces that the given value is true, throwing an `ErrnoException` if it
566562
is not.

0 commit comments

Comments
 (0)