Skip to content

Commit

Permalink
Fix Bugzilla 22293: opCast!bool for Nullable
Browse files Browse the repository at this point in the history
The second opCast overload is necessary to allow built-in implicit
conversions (e.g., mutable to const) to be performed explicitly via a
cast expression. Nullable.opEquals depends on this behavior.
  • Loading branch information
pbackus committed Jul 31, 2024
1 parent a6ad152 commit 986ba65
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions std/typecons.d
Original file line number Diff line number Diff line change
Expand Up @@ -3543,6 +3543,35 @@ struct Nullable(T)
format!"%s"(a);
}

/**
* Returns true if `this` has a value, otherwise false.
*
* Allows a `Nullable` to be used as the condition in an `if` statement:
*
* ---
* if (auto result = functionReturningNullable())
* {
* doSomethingWith(result.get);
* }
* ---
*/
bool opCast(T : bool)() const
{
return !isNull;
}

/// Prevents `opCast` from disabling built-in conversions.
auto ref T opCast(T, this This)()
if (is(This : T) || This.sizeof == T.sizeof)
{
static if (is(This : T))
// Convert implicitly
return this;
else
// Reinterpret
return *cast(T*) &this;
}

/**
* Forces `this` to the null state.
*/
Expand Down Expand Up @@ -4400,6 +4429,26 @@ auto nullable(T)(T t)
assert(destroyed);
}

// https://issues.dlang.org/show_bug.cgi?id=22293
@safe unittest
{
Nullable!int empty;
Nullable!int full = 123;

assert(cast(bool) empty == false);
assert(cast(bool) full == true);

if (empty) assert(0);
if (!full) assert(0);
}

// check that opCast doesn't break unsafe casts
@system unittest
{
Nullable!(const(int*)) a;
auto result = cast(immutable(Nullable!(int*))) a;
}

/**
Just like `Nullable!T`, except that the null state is defined as a
particular value. For example, $(D Nullable!(uint, uint.max)) is an
Expand Down

0 comments on commit 986ba65

Please sign in to comment.