Fix nested this capture for traits(getMember, this, ...) - #5205
Conversation
21ecdf4 to
46d1820
Compare
| return ErrorExp.get(); | ||
| } | ||
| } | ||
| // wantsym returns the member symbol; using `this` as the lookup object |
There was a problem hiding this comment.
Is this in upstream DMD? if not, if should go there first.
There was a problem hiding this comment.
DMD seems to work fine without this, so the fix should probably be somewhere in our glue layer instead. [Unless it's one of the few LDC-specific frontend mods that cause this.]
There was a problem hiding this comment.
Thanks for the review , looked at upstream DMD.
Upstream: On current dlang/dmd master, compiler/src/dmd/traits.d has the same getMember path and does not call checkNestedReference when the first argument is this, so this isn’t LDC-specific. I didn’t find an existing dlang/dmd issue for it yet.
approach I’ll open an issue + PR on dlang/dmd with the semantic fix and a runnable test, then align this LDC PR with however you prefer we track upstream (cherry-pick / wait for DMD merge / close LDC PR until sync).
CI: The remaining failures are from tests/dmd/runnable/issue5203.d, not merge approval. The test used return get2 (returns int) instead of return &get2 (delegate). I’m fixing it to use an lvalue + auto dg = s.nestedThunk(); assert(dg() == 42) and will push once we agree on upstream-first vs keeping this PR open as a tracker.
There was a problem hiding this comment.
so this isn’t LDC-specific
The testcase doesn't fail with DMD v2.112: https://godbolt.org/z/sKcPabbE8
So what I meant is that DMD doesn't need the proposed frontend patch, so there must be something else LDC-specific that causes it.
There was a problem hiding this comment.
@kinke Thanks ,that’s the distinction I missed.
I checked Godbolt with DMD 2.112: the testcase runs without a traits.d change, so I agree this isn’t “upstream DMD is broken the same way.” The ldc#5203 report is LDC-specific at runtime,
Next steps :
- Re-run the original ldc#5203 repro (and your Godbolt source) with dmd vs ldc on the same frontend line , compile and run (segfault is runtime).
- Trace whether
vthis/ nested frame is missing in LDC glue (gen/nested, closure lowering) vs a frontend path that only LDC exercises. - Align
issue5203.dwith the reporter’s pattern before any further pushes here.
I’ll report back on this thread with dmd/ldc comparison results before pushing more frontend changes.
|
This agent seems too eager, not controlled sufficiently by a human. And no LLM disclosure in the commit messages, not ideal either. |
|
here is what I found. Godbolt’s example and ldc issue #5203 are not the same shape. On LDC I traced the crash to missing capture metadata. When the nested body only reaches locally I added an LDC only block under I am rebuilding ldc2 on my machine to run that test, soif it passes I will update the branch. |
Right, so what does DMD do instead, in order not to hit this problem? Maybe it's using a whole different scheme and doesn't create a frame with the closure-vars, but uses the whole stack frame of the function, or something like that. In that case (again, just a guess), we wouldn't want that for LDC, so would need a workaround indeed. |
|
both compilers still use the same frontend lists. The difference shows up when something was never added to that list. here it matches what you saw on Godbolt The fix we have locally is |
…his, ...) __traits(getMember, this, field) with wantsym never keeps a ThisExp, so checkNestedReference was skipped and LDC omitted the outer this from the nested frame (gen/nested). Gate the capture under version (IN_LLVM), matching getThisSkipNestedFuncs. Regression covers an escaping nested delegate.
6620c06 to
e4ea1ee
Compare
|
@kinke branch updated: |
Summary
Nested functions that only touch an instance field through
__traits(getMember, this, "member")never registered a nested reference to the enclosing memberthis. LDC then omittedvthisfrom the closure frame, which showed up as a segfault when the nested function ran (#5203).After semantic analysis of
getMember, when the lookup object isthis, callcheckNestedReferenceon the member function'svthisso closure building matches a direct field access.Test plan
Added
tests/dmd/runnable/issue5203.dcovering a nested function returned as a delegate that reads a field viagetMemberonthis.Fixes #5203.