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

Fix 23722 - Lambdas are mangled incorrectly when using multiple compi… #15343

Merged
merged 2 commits into from
Nov 27, 2024

Conversation

dkorpel
Copy link
Contributor

@dkorpel dkorpel commented Jun 23, 2023

…lation units, resulting in incorrect code

The problem now is that FuncExp in an alias is emitted in neither compilation unit, resulting in an undefined reference error.

@dkorpel dkorpel added the Review:WIP Work In Progress - not ready for review or pulling label Jun 23, 2023
@dlang-bot
Copy link
Contributor

dlang-bot commented Jun 23, 2023

Thanks for your pull request and interest in making D better, @dkorpel! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

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.

⚠️⚠️⚠️ Warnings ⚠️⚠️⚠️

  • In preparation for migrating from Bugzilla to GitHub Issues, the issue reference syntax has changed. Please add the word "Bugzilla" to issue references. For example, Fix Bugzilla Issue 12345 or Fix Bugzilla 12345.(Reminder: the edit needs to be done in the Git commit message, not the GitHub pull request.)

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 "stable + dmd#15343"

@@ -0,0 +1,16 @@
// COMPILE_SEPARATELY:
// EXTRA_SOURCES: imports/test23722b.d
// REQUIRED_ARGS: -betterC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No

@PetarKirov
Copy link
Member

@dkorpel I've rebased your PR to see how it fares on the CI nowadays.

@PetarKirov
Copy link
Member

Not ready (yet):

... runnable/test23722.d           -betterC  -fPIC (-inline -release -g -O)==============================
Test 'runnable/test23722.d' failed. The logged output:
/home/runner/work/dmd/dmd/generated/linux/release/64/dmd -conf= -m64 -Irunnable -betterC  -fPIC  -odtest_results/runnable -c  runnable/test23722.d
/home/runner/work/dmd/dmd/generated/linux/release/64/dmd -conf= -m64 -Irunnable -betterC  -fPIC  -odtest_results/runnable -c  runnable/imports/test23722b.d
/home/runner/work/dmd/dmd/generated/linux/release/64/dmd -conf= -m64  -fPIC  -odtest_results/runnable -oftest_results/runnable/test23722_0 test_results/runnable/test23722.o test_results/runnable/test23722b.o
test_results/runnable/test23722.o:runnable/test23722.d:function _D9test237224do_yFZv: error: undefined reference to '_D10test23722b1A14__lambda_L6_C5FNbNiZv'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
==============================
Test 'runnable/test23722.d' failed: Expected rc == 0, but exited with rc == 1

@yanok
Copy link
Contributor

yanok commented Nov 20, 2024

Is this abandoned? Should I create a new PR? This is a quite nasty issue, can cause calling incorrect function at runtime.

@yanok
Copy link
Contributor

yanok commented Nov 20, 2024

@dkorpel Do you plan to update this PR?

@thewilsonator
Copy link
Contributor

Should I create a new PR?

Yes, rebases of old PRs are always welcome. Note that this one failed CI so will need some changes.

@dkorpel
Copy link
Contributor Author

dkorpel commented Nov 20, 2024

I'll rebase this and take another look at the undefined reference problem

@yanok
Copy link
Contributor

yanok commented Nov 20, 2024

I'll rebase this and take another look at the undefined reference problem

Thanks a lot! I've also updated the bug. tl;dr: I believe this fix is a correct one, but the example in the bug triggers two separate issues, and the second one gets uncovered by this fix.

@dkorpel
Copy link
Contributor Author

dkorpel commented Nov 20, 2024

Yes, perhaps the test case should have -allinst for now.

Edit: not sure that affects the test case actually

@yanok
Copy link
Contributor

yanok commented Nov 20, 2024

Well, it's not an instantiation, so I think -allinst is not supposed to help. I've posted a smaller example that fails to compile due to this issue, you could use it as a test for the lambda naming issue.

Copy link
Contributor

@thewilsonator thewilsonator left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Please resolve as appropriate 3706959#r1239935088

@yanok
Copy link
Contributor

yanok commented Nov 21, 2024

Uh, unfortunately I don't think that's a full fix... It's a bit more complicated than that.

generateIdWithLoc has additional logic to make the ids unique by adding a suffix if the same (prefix, loc) is requested more than once. But that's precisely what we want to avoid with lambdas and separate compilation: we could end up referencing both __lambda_LOC and __lambda_LOC_1, while the module with the definition only has __lambda_LOC...

@dkorpel
Copy link
Contributor Author

dkorpel commented Nov 21, 2024

You're right. I recall unittests used to simply use a counter, which wouldn't be stable with separate compilation.
Then the idea was to use source location, which is deterministic, but not unique when using templates / mixins / static foreach etc.
So now we have source location + counter, which works either with separate compilation or templates, but not both at the same time.

Hashing the function body wouldn't work, because you can have multiple identical anonymous functions.

The only thing I can think of is keeping track of a stack of instantation locations and combining all those until you get something unique.

@dkorpel dkorpel marked this pull request as ready for review November 21, 2024 23:43
@yanok
Copy link
Contributor

yanok commented Nov 22, 2024

You're right. I recall unittests used to simply use a counter, which wouldn't be stable with separate compilation. Then the idea was to use source location, which is deterministic, but not unique when using templates / mixins / static foreach etc. So now we have source location + counter, which works either with separate compilation or templates, but not both at the same time.

I think templates and mixins are covered, since they will have all the instantiations/mixins in the final symbol name, the only place there we really need to make lambda names based on Loc unique is static foreach and loop unrolling. I've added a commit yanok@19f6680 on top of your changes to implement this. PTAL. That combination makes it work for me (we are using LDC).

I failed to make a really failing example to showcase the problem with making lambdas inside templates even more unique, probably that problem with missing symbols I saw is LDC specific... What I can get with DMD so far is only code duplication: mod1.o contains f!1.__lambda_LOC_1 and mod2.o has f!1.__lambda_LOC while they are exactly the same (and had the same name before your changes).

The only thing I can think of is keeping track of a stack of instantation locations and combining all those until you get something unique.

Yes, that's the idea! We don't need to track them, I think, since the parent scope name is already what we want. Also, just adding that directly to the lambda ident will work, but with a lot of duplication. D's symbols are already long enough ;)

@dkorpel
Copy link
Contributor Author

dkorpel commented Nov 27, 2024

Meanwhile I'll merge this as a partial fix, making a note in the issue.

@dkorpel dkorpel merged commit a3abf11 into dlang:stable Nov 27, 2024
73 checks passed
@dkorpel dkorpel deleted the lambda-mangle branch November 27, 2024 11:03
kinke added a commit to kinke/dmd that referenced this pull request Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Review:WIP Work In Progress - not ready for review or pulling Severity:Bug Fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants