Skip to content

Lightweight getMember resolution for aggregate types#22546

Draft
CyberShadow wants to merge 1 commit intodlang:masterfrom
CyberShadow:getMember-lazy-dsymbol
Draft

Lightweight getMember resolution for aggregate types#22546
CyberShadow wants to merge 1 commit intodlang:masterfrom
CyberShadow:getMember-lazy-dsymbol

Conversation

@CyberShadow
Copy link
Copy Markdown
Member

@CyberShadow CyberShadow commented Feb 9, 2026

Generated by Claude Opus 4.6, usual disclaimers apply.

Implements the idea in #22541 (comment) .

Supersedes #22541, #22542, and #22545.


When __traits(getMember, T, name) is used inside allMembers loops on
template struct types, the normal path through expressionSemantic
triggers functionSemantic → functionSemantic3 (eager body compilation)
on member functions, causing circular dependency errors.

Add a lightweight fast path in getMember that resolves via sym.search()
and returns a DsymbolExp with the type pre-set, bypassing the cascade.
This covers both auto-return functions (inferRetType) and instantiated
functions in template structs (isInstantiated).

Also handle DsymbolExp in TemplateInstance_semanticTiargs so that
function symbols are stored directly as Dsymbols rather than being
passed to ctfeInterpret, which would fail.

@dlang-bot
Copy link
Copy Markdown
Contributor

Thanks for your pull request, @CyberShadow!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#22546"

@CyberShadow CyberShadow force-pushed the getMember-lazy-dsymbol branch 4 times, most recently from 9e295a8 to 74ced6d Compare February 9, 2026 19:49
@CyberShadow CyberShadow marked this pull request as ready for review February 9, 2026 21:03
@CyberShadow
Copy link
Copy Markdown
Member Author

@dkorpel What do you think about this one? I don't fully understand it, but it's green and the diff is small 😛

@CyberShadow CyberShadow changed the title Lightweight symbol resolution for getMember, getOverloads, and getVirtualMethods Lightweight getMember resolution for aggregate types Feb 9, 2026
@tim-dlang
Copy link
Copy Markdown
Contributor

I like the approach, but this can cause regressions, when the result of __traits(getMember, ...) is used in different ways, for example:

struct S(T)
{
    static void f()
    {
    }
}
pragma(msg, __traits(getMember, S!int, "f").mangleof);

With DMD v2.112.0 this prints _D17testlazygetmember__T1STiZQf1fFNaNbNiNfZv, but with this PR it only prints FZv.

CTFE also does not work anymore:

struct S(T)
{
    static int f()
    {
        return 42;
    }
}
pragma(msg, __traits(getMember, S!int, "f")());

DMD with this PR prints the following:

testlazygetmember.d(51): Error: cannot interpret `f` at compile time
pragma(msg, __traits(getMember, S!int, "f")());
            ^
testlazygetmember.d(51):        while evaluating `pragma(msg, f())`
pragma(msg, __traits(getMember, S!int, "f")());
^

When __traits(getMember, T, name) is used inside allMembers loops on
template struct types, the normal path through expressionSemantic
triggers functionSemantic → functionSemantic3 (eager body compilation)
on member functions, causing circular dependency errors.

Add a lightweight fast path in getMember that resolves via sym.search()
and returns a DsymbolExp with the type pre-set, bypassing the cascade.
This covers both auto-return functions (inferRetType) and instantiated
functions in template structs (isInstantiated).

Also handle DsymbolExp in TemplateInstance_semanticTiargs so that
function symbols are stored directly as Dsymbols rather than being
passed to ctfeInterpret, which would fail.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@CyberShadow
Copy link
Copy Markdown
Member Author

Argh, good catch. Let me have a look.

@CyberShadow CyberShadow marked this pull request as draft February 10, 2026 09:31
@CyberShadow CyberShadow force-pushed the getMember-lazy-dsymbol branch from 74ced6d to 4ec6296 Compare February 10, 2026 09:31
@CyberShadow CyberShadow added the AI Generated Code that is generated by an LLM AI. label Feb 13, 2026
@CyberShadow
Copy link
Copy Markdown
Member Author

@tim-dlang Latest revision adds more isDsymbolExp checks which fixes those two issues. Does this direction make sense?

@tim-dlang
Copy link
Copy Markdown
Contributor

Yes, I think the direction makes sense. I worry that other traits, properties or is expressions could still have problems, but maybe the traits work, because they use the common function getDsymbolWithoutExpCtx, which is already modified by this PR.

Here is another failing test case:

struct S5(int line)
{
    static void badfunc()
    {
        undefined;
    }
}

static assert(!__traits(compiles,__traits(getMember, S5!__LINE__, "badfunc")));
static assert(!is(typeof(__traits(getMember, S5!__LINE__, "badfunc"))));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Code that is generated by an LLM AI.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants