Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__traits(parent, sym) gives back sym itself when sym is an instantiation of a multi-layered eponymous template #21005

Open
jmdavis opened this issue Mar 16, 2025 · 0 comments
Labels
Feature:traits Relating to __traits

Comments

@jmdavis
Copy link
Member

jmdavis commented Mar 16, 2025

This code

void main()
{
}

template Type()
{
    struct Type()
    {
    }
}

alias Partial = Type!();

pragma(msg, __traits(parent, Partial!()));

import std.traits;
pragma(msg, moduleName!(Partial!()));

fails to compile, printing out

Partial!()
/usr/local/include/dmd/std/traits.d(508): Error: alias `std.traits.moduleName!(Partial!()).moduleName` recursive alias declaration
alias moduleName = moduleName!(parentOf!T); // If you use enum, it will cause compiler ICE
^
test.d(17): Error: template instance `std.traits.moduleName!(Partial!())` error instantiating
pragma(msg, moduleName!(Partial!()));
^
test.d(17):        while evaluating `pragma(msg, moduleName!(Partial!()))`
pragma(msg, moduleName!(Partial!()));
^

parentOf is a private trait in std.traits which is a wrapper around __traits(parent, ...). So, the line that's failing is basically

alias moduleName = moduleName!(__traits(parent, T));

and as the pragma(msg, ...) line shows, the parent of Partial!() is apparently itself. So, when moduleName grabs the parent of Partial!(), it then attempts to instantiate another instance of moduleName with the exact same argument again - hence the error about a recursive alias declaration.

My guess is that the problem relates to the fact that Type is an eponymous template. So, the templated type inside the template has the same name. And it seems to only happen when the type inside the template is itself templated. And unsurprisingly, if that's fully written out as

template Type()
{
    template Type()
    {
        struct Type
        {
        }
    }
}

the error is the same.

So, the bug here is that in this particular case, __traits(parent, ...) is giving back the same symbol that it's given instead of the parent of that symbol.

The instance where I ran into this in real code of course had template parameters for both templates, so the number of template parameters doesn't seem to matter. The example here is simply the simplest test case that I found when attempting to reduce it.

@jmdavis jmdavis added the Feature:traits Relating to __traits label Mar 16, 2025
atilaneves added a commit to atilaneves/unit-threaded that referenced this issue Mar 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:traits Relating to __traits
Projects
None yet
Development

No branches or pull requests

1 participant