hasElaborateDestructor!T is not stable for self-referential types.
If first evaluated while T is still incomplete, hasElaborateDestructor!T evaluates to false, and subsequent evaluations for the same type also produce false.
If first evaluated after T has been completely defined, it evaluates to true.
As a result, the final value depends on where the template is first instantiated, violating the expectation that a type trait should depend only on the type itself.
Expected:
For a given type, hasElaborateDestructor!T should always produce the same result regardless of instantiation order.
Actual:
The result depends on where the template is first instantiated.
NG case:
import std.traits;
struct Recursive(T)
{
// static assert: `hasElaborateDestructor!(Node)` is false
static assert(hasElaborateDestructor!T);
}
struct Node
{
Recursive!Node next;
~this() {}
}
void main() {}
Expected: Node has a user-defined destructor, so hasElaborateDestructor!Node should be true.
Actual: hasElaborateDestructor!Node evaluates to false because Node is instantiated while still incomplete.
And once hasElaborateDestructor!Node is evaluated at this point, subsequent evaluations of the same trait for Node also produce false, even after Node has been completely defined.
OK case:
import std.traits;
struct Recursive(T)
{
}
struct Node
{
Recursive!Node next;
~this() {}
}
static assert(hasElaborateDestructor!Node); // OK
void main() {}
This produces the expected result because Node is complete when the trait is evaluated.
This will be the intended result.
hasElaborateDestructor!Tis not stable for self-referential types.If first evaluated while T is still incomplete,
hasElaborateDestructor!Tevaluates to false, and subsequent evaluations for the same type also produce false.If first evaluated after T has been completely defined, it evaluates to true.
As a result, the final value depends on where the template is first instantiated, violating the expectation that a type trait should depend only on the type itself.
Expected:
For a given type, hasElaborateDestructor!T should always produce the same result regardless of instantiation order.
Actual:
The result depends on where the template is first instantiated.
NG case:
Expected: Node has a user-defined destructor, so
hasElaborateDestructor!Nodeshould be true.Actual:
hasElaborateDestructor!Nodeevaluates to false because Node is instantiated while still incomplete.And once
hasElaborateDestructor!Nodeis evaluated at this point, subsequent evaluations of the same trait for Node also produce false, even after Node has been completely defined.OK case:
This produces the expected result because Node is complete when the trait is evaluated.
This will be the intended result.