Skip to content

hasElaborateDestructor returns different results depending on the first instantiation point for incomplete self-referential types #23352

Description

@shoo

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions