Skip to content

Commit

Permalink
Merge pull request #6043 from quickfur/issue17440b
Browse files Browse the repository at this point in the history
Fix issue 17440: do not call .destroy on class instances in Nullable.nullify
merged-on-behalf-of: Steven Schveighoffer <schveiguy@users.noreply.github.com>
  • Loading branch information
dlang-bot authored Jan 18, 2018
2 parents 6415314 + 04c5935 commit 0666fc6
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
27 changes: 27 additions & 0 deletions changelog/nullable-class.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
`Nullable!C.nullify` no longer calls .destroy when `C` is a class or interface

Previously, when `.nullify` is called on a `Nullable!C` where `C` is a class or
interface, the underlying object is destructed immediately via the `.destroy`
function. This led to bugs when there are still references to the object
outside of the `Nullable` instance:

------
class C
{
int canary = 0xA71FE;
~this()
{
canary = 0x5050DEAD;
}
}

auto c = new C;
assert(c.canary == 0xA71FE);

Nullable!C nc = nullable(c);
nc.nullify;
assert(c.canary == 0xA71FE); // This would fail
------

The `.nullify` method has been fixed so that it no longer calls `.destroy` on
class or interface instances, and the above code will now work correctly.
30 changes: 29 additions & 1 deletion std/typecons.d
Original file line number Diff line number Diff line change
Expand Up @@ -2508,7 +2508,10 @@ Forces $(D this) to the null state.
*/
void nullify()()
{
.destroy(_value);
static if (is(T == class) || is(T == interface))
_value = null;
else
.destroy(_value);
_isNull = true;
}

Expand Down Expand Up @@ -2965,6 +2968,31 @@ auto nullable(T)(T t)
var.nullify;
}

// Issue 17440
@system unittest
{
static interface I { }

static class C : I
{
int canary;
~this()
{
canary = 0x5050DEAD;
}
}
auto c = new C;
c.canary = 0xA71FE;
auto nc = nullable(c);
nc.nullify;
assert(c.canary == 0xA71FE);

I i = c;
auto ni = nullable(i);
ni.nullify;
assert(c.canary == 0xA71FE);
}

/**
Just like $(D 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 0666fc6

Please sign in to comment.