-
-
Notifications
You must be signed in to change notification settings - Fork 749
Open
Copy link
Labels
Severity:RegressionIssues that are regressions/PRs that fix regressionsIssues that are regressions/PRs that fix regressions
Description
I've found what seems to be a regression related to the hasElaborateDestructor trait.
When compiling and running the following code with DMD 2.110.0, I get this output:
~C(0)
a.b.len=1
b.c.len=0
exit
~B(): c.len=0
~A(): b.len=1
~B(): c.len=1
~C(1)
However, when compiled with DMD 2.111.0, I get:
No destructor found for B
No destructor found for C
~C(1)
a.b.len=1
b.c.len=0
exit
~B(): c.len=0
~A(): b.len=1
So it seems that in 2.111.0 the compiler incorrectly determines that B and C have no destructors, even though they clearly do.
Here’s the minimal reproducible example:
import core.lifetime : moveEmplace;
import core.stdc.stdio : printf;
import core.stdc.stdlib : malloc, realloc, free;
import std.algorithm : max;
import std.traits : hasElaborateDestructor, isImplicitlyConvertible;
void main()
{
A a;
B b;
b.c ~= C(1);
a.b ~= b;
printf("a.b.len=%ld\n", a.b.len);
printf("b.c.len=%ld\n", b.c.len);
printf("exit\n");
}
struct Array(T, size_t step = 64)
{
@disable this(this);
this(size_t cap) @trusted nothrow @nogc {
buf = (cast(T*)malloc(T.sizeof * cap))[0..cap];
}
~this() nothrow @nogc {
if (buf) {
static if (hasElaborateDestructor!T) {
foreach (ref item; buf[0..len]) destroy(item);
}
else pragma(msg, "No destructor found for ", T);
free(buf.ptr);
}
}
void reserve(size_t elements) @trusted nothrow @nogc {
if (buf.length - len >= elements) return;
const newLen = buf.length + max(elements, step);
if (!buf)
buf = (cast(T*)malloc(T.sizeof * newLen))[0..newLen];
else
buf = (cast(T*)realloc(buf.ptr, T.sizeof * newLen))[0..newLen];
}
void put(U)(auto ref scope U item) @trusted
if (isImplicitlyConvertible!(U, T))
{
reserve(1);
() @trusted { item.moveEmplace(buf[len++]); }();
}
alias opOpAssign(string op : "~") = put;
private:
T[] buf;
size_t len;
}
struct A {
Array!B b;
~this() nothrow @nogc {
printf("~A(): b.len=%ld\n", b.len);
}
}
struct B {
Array!C c;
~this() nothrow @nogc {
printf("~B(): c.len=%ld\n", c.len);
}
}
struct C {
int foo;
~this() nothrow @nogc {
printf("~C(%d)\n", foo);
}
}Expected behavior:
hasElaborateDestructor!B and hasElaborateDestructor!C should return true (as in 2.110.0), since both types define destructors.
Actual behavior:
Starting with 2.111.0, both are incorrectly reported as having no destructors.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Severity:RegressionIssues that are regressions/PRs that fix regressionsIssues that are regressions/PRs that fix regressions