cat > bug.d << CODE
struct Vector
{
~this()
{
}
RefCounted!Vector dup()
{
return RefCounted!Vector(&this);
}
}
struct RefCounted(T)
{
~this()
{
.destroy(*t); // __xdtor of Vector not yet available
static assert(__traits(hasMember, T, "__xdtor"));
}
T* t;
}
CODE
dmd -c bug
----
bug.d(18): Error: static assert (__traits(hasMember, Vector, "__xdtor")) is false
bug.d(7): instantiated from here: RefCounted!(Vector)
----
The problem is that __xdtor is not yet available when the destructor of RefCounted is analyzed, hence .destroy won't call the destructor of Vector.
It seems that the creation of __xdtor should happen earlier.
Comment #1 by code — 2015-09-12T00:07:01Z
This breaks b/c of the following semantic analysis issue.
Vector.semantic
dup.semantic
RefCounted!Vector.semantic (return type)
RefCounted!Vector buildOpAssign
RefCounted!Vector.dtor.semantic3 (buildOpAssign)
It seems that buildOpAssign is too greedy running semantic3 during a semantic1 pass of a struct.
Comment #2 by code — 2015-09-12T01:26:52Z
Any idea how to solve this @Kenji?
We could try to do semantic3 for buildOpAssign later, but then we'd have to add a special case to op_overload and gag assign usage or so.
Comment #3 by k.hara.pg — 2015-09-14T10:44:06Z
(In reply to Martin Nowak from comment #2)
> Any idea how to solve this @Kenji?
> We could try to do semantic3 for buildOpAssign later, but then we'd have to
> add a special case to op_overload and gag assign usage or so.
I think currently there's no way than treat the generated opAssign function specially.
I'll post a PR soon.