Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions changelog/remove-nullable-alias-get-this.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
`Nullable` `alias get this` has been deprecated

`Nullable`'s feature of implicitly converting to its contained value has been marked deprecated.

All sites where a `Nullable!T` is implicitly converted to `T`, potentially throwing an error at runtime,
will now produce a deprecation warning or error with `-de`.

To fix this, explicitly use `.get` to access the contained value of the `Nullable`.

`alias get this` is the only implicit conversion in D that may throw an error. Since it is an implicit conversion,
it can easily be used accidentally and lead to unexpected runtime errors. By explicitly invoking `get`,
the developer acknowledges that the operation has a chance of error. Conversely, by not implicitly converting
`Nullable!T` to `T`, the compiler gives the developer a chance to spot forgotten `isNull` checks.

This feature will be removed after release 2.096.
69 changes: 36 additions & 33 deletions std/typecons.d
Original file line number Diff line number Diff line change
Expand Up @@ -2960,7 +2960,6 @@ Params:
Gets the value if not null. If `this` is in the null state, and the optional
parameter `fallback` was provided, it will be returned. Without `fallback`,
calling `get` with a null state is invalid.
This function is also called for the implicit conversion to `T`.

Params:
fallback = the value to return in case the `Nullable` is null.
Expand All @@ -2981,7 +2980,9 @@ Returns:
return isNull ? fallback : _value.payload;
}

///
//@@@DEPRECATED_2.096@@@
deprecated(
"Implicit conversion with `alias Nullable.get this` will be removed after 2.096. Please use `.get` explicitly.")
@system unittest
{
import core.exception : AssertError;
Expand All @@ -2999,24 +3000,33 @@ Returns:
assert(i == 5);
}

//@@@DEPRECATED_2.096@@@
deprecated(
"Implicit conversion with `alias Nullable.get this` will be removed after 2.096. Please use `.get` explicitly.")
@property ref inout(T) get_() inout @safe pure nothrow
{
return get;
}

///
@safe pure nothrow unittest
{
int i = 42;
Nullable!int ni2;
int x = ni2.get(i);
Nullable!int ni;
int x = ni.get(i);
assert(x == i);

ni2 = 7;
x = ni2.get(i);
ni = 7;
x = ni.get(i);
assert(x == 7);
}

/**
Implicitly converts to `T`.
`this` must not be in the null state.
This feature is deprecated and will be removed after 2.096.
*/
alias get this;
alias get_ this;
}

/// ditto
Expand Down Expand Up @@ -3046,8 +3056,8 @@ auto nullable(T)(T t)
if (!queryResult.isNull)
{
//Process Mr. Doe's customer record
auto address = queryResult.address;
auto customerNum = queryResult.customerNum;
auto address = queryResult.get.address;
auto customerNum = queryResult.get.customerNum;

//Do some things with this customer's info
}
Expand All @@ -3071,6 +3081,9 @@ auto nullable(T)(T t)
assertThrown!Throwable(a.get);
}

//@@@DEPRECATED_2.096@@@
deprecated(
"Implicit conversion with `alias Nullable.get this` will be removed after 2.096. Please use `.get` explicitly.")
@system unittest
{
import std.exception : assertThrown;
Expand Down Expand Up @@ -3124,10 +3137,10 @@ auto nullable(T)(T t)
assert(s == S(6));
assert(s != S(0));
assert(s.get != S(0));
s.x = 9190;
assert(s.x == 9190);
s.get.x = 9190;
assert(s.get.x == 9190);
s.nullify();
assertThrown!Throwable(s.x = 9441);
assertThrown!Throwable(s.get.x = 9441);
}
@safe unittest
{
Expand Down Expand Up @@ -3156,7 +3169,7 @@ auto nullable(T)(T t)
assert(s.isNull);
s = S(5);
assert(!s.isNull);
assert(s.x == 5);
assert(s.get.x == 5);
s.nullify();
assert(s.isNull);
}
Expand Down Expand Up @@ -3276,10 +3289,10 @@ auto nullable(T)(T t)
auto x2 = immutable Nullable!S1(sm);
auto x3 = Nullable!S1(si);
auto x4 = immutable Nullable!S1(si);
assert(x1.val == 1);
assert(x2.val == 1);
assert(x3.val == 1);
assert(x4.val == 1);
assert(x1.get.val == 1);
assert(x2.get.val == 1);
assert(x3.get.val == 1);
assert(x4.get.val == 1);
}

auto nm = 10;
Expand All @@ -3292,8 +3305,8 @@ auto nullable(T)(T t)
static assert(!__traits(compiles, { auto x2 = immutable Nullable!S2(sm); }));
static assert(!__traits(compiles, { auto x3 = Nullable!S2(si); }));
auto x4 = immutable Nullable!S2(si);
assert(*x1.val == 10);
assert(*x4.val == 10);
assert(*x1.get.val == 10);
assert(*x4.get.val == 10);
}

{
Expand All @@ -3303,10 +3316,10 @@ auto nullable(T)(T t)
auto x2 = immutable Nullable!S3(sm);
auto x3 = Nullable!S3(si);
auto x4 = immutable Nullable!S3(si);
assert(*x1.val == 10);
assert(*x2.val == 10);
assert(*x3.val == 10);
assert(*x4.val == 10);
assert(*x1.get.val == 10);
assert(*x2.get.val == 10);
assert(*x3.get.val == 10);
assert(*x4.get.val == 10);
}
}
@safe unittest
Expand Down Expand Up @@ -3397,16 +3410,6 @@ auto nullable(T)(T t)
assert(c.canary == 0xA71FE);
}

// Regression test for issue 18539
@safe unittest
{
import std.math : approxEqual;

auto foo = nullable(2.0);
auto bar = nullable(2.0);

assert(foo.approxEqual(bar));
}
// bugzilla issue 19037
@safe unittest
{
Expand Down