-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Do not give the default C++ constructor's return statement a result. #32534
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
[cxx-interop] Do not give the default C++ constructor's return statement a result. #32534
Conversation
…ent a result. The default C++ object constructor assigns the newly created object out of the function so, it should not return a value. Returning a value will trigger SILGen assertions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense! As a followup, it'd be good to check that the elementwise constructor still does the right thing with possibly nontrivial fields if the imported type is non-empty.
@jckarter good idea, will do. Thanks. |
@swift-ci please smoke test and merge. |
1 similar comment
@swift-ci please smoke test and merge. |
@zoecarver Sorry for the late review, but could you adjust the test to have a stronger postcondition than just "does not crash"? Could you add a SILGen test that checks the actual SIL instructions in the body of the generated no-arg initializer in the |
@zoecarver Another question is why is this issue only caught by assertions (I assume AST or SIL verifier?) only for C++ types? Are we missing some AST or SIL verifier checks? |
Sure. Will do.
The assertion was only caught for C++ types because the issue with this constructor was only visible for address types. I'm not sure if there are any non-c++ address only types that are default constructible (and if so, we should make tests for them). |
Also, for what it's worth, this crashed in SILGen IRC. If it had been able to generate the function, the SILVerifier probably would have errored. |
WDYM by "visible"? Is it valid to |
Hmm, I think you're right. It would make sense that the verifier should catch that sort of error. I'll make a patch to add a verifier check for this tomorrow. Looking at it again, for a loadable C++ type, we sill generate a return statement with an empty tuple, but it looks like the SIL function actually does return a value. Any idea how that happens? |
@zoecarver The conversion to indirect return is part of SILGen's job. The AST should still formally return a result, but because the type is not loadable when lowered to SIL, it should result in the SIL function getting an indirect return argument, and writing the result to that, instead of returning by value. If you've already modified SIL type lowering so that nontrivial C++ types are classified as address-only, then that should just work, and if it isn't, it sounds like we still have work to do to figure out why. |
@jckarter my confusion is because in
Yes, currently everything works. I'm just curious as to why. It seems like what we maybe should have done is returned the call to |
To elaborate a bit: Assigning self out of the function seems like it shouldn't work but, it does. Especially for loadable structs, assigning one value type to another seems like it should have no effect in the worst case, and error in the best case. The reason this works is SILGen somehow figures out what we're trying to do is emit a return of the newly created object. I don't know much about SILGen so, I'm not sure if this is the conventional way to do things but, I suspect it's not. |
It could be that the code path in
with
Since Int is a trivial loadable type, |
I agree. It's likely it hasn't. I'll create a new patch to update this function and similar ones to work with address types. When building the AST, we don't have to create a special path for address type, or do we? In other words, can I just create a Thanks for the help :) |
Right -- at the AST level we don't even know whether the type is address-only or loadable, so the AST for the no-arg initializer should be identical between the two. My suggestion regarding the verifier seems to be relevant for the AST verifier then. If SILGen wants a specific shape of |
Sorry for all the back and forth. I went to go make this change and I realized because of how the constructor body synthesizer works, we actually aren't allowed to directly create the return statement in the synthesizer function. So, I think the change this PR made is good. I will add the AST verifier check, though. |
@zoecarver Yeah, if we're able to make it so that the intended semantics of the initializer can be synthesized into the AST, then we should be able to allow SILGen to just do its thing lowering a regular function body without special code. |
The default C++ object constructor assigns the newly created object out of the function so, it should not return a value. Returning a value will trigger SILGen assertions.
Refs #32402.