-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Mark types with a destructor a non-trivial. #32402
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] Mark types with a destructor a non-trivial. #32402
Conversation
@gottesmm, could you review SILGen changes? |
5c0cac2
to
3c9b1be
Compare
lib/SILGen/SILGenStmt.cpp
Outdated
tupleInit->SubInitializations.push_back(std::move(eltInit)); | ||
} | ||
// If this is an empty tuple, we don't want to decompose it. | ||
if (resultTupleType.getElementTypes().size()) { |
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.
Did this need to be changed?
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.
IOW, I don't understand why this change requires this other fix. Does a crash result? Please explain this to me?
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.
Yes. Using any type with a user-provided destructor crashes without this fix.
When we have an empty tuple, we get the wrong return type later on. Because the value is returned with an indirect result, the return type should be @out Foo
but instead is ()
(because that's what's returned).
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.
TBH, I'm not sure this is the right fix. It did fix the problem and (seems like?) it doesn't have any unwanted side effects but, it doesn't fix the "root" of the issue. I can investigate this a bit more.
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.
Yes. Maybe @jckarter or @slavapestov have ideas.
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.
@jckarter the assertion on line 451: assert(allResults.empty());
.
Because in prepareIndirectResultInit
the tuple path is taken and the tuple is empty, the results aren't recursively slice
d off allResults
.
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.
FWIW I suspect this is probably slower (it goes from essentially a no-op to a recursive function that will dynamically allocate memory).
Edit: scratch that; both paths will allocate something.
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.
@zoecarver If the result type is an empty tuple, though, then there shouldn't be anything in allResults
to slice off to begin with. Do you know what the root of the change in behavior is?
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.
@jckarter sorry this comment slipped through my inbox somehow. I can spend some time today looking into this in more depth.
Do you know what the root of the change in behavior is?
I don't know.
If the result type is an empty tuple, though, then there shouldn't be anything in allResults to slice off to begin with.
I think allResults
holds indirect results (also?).
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.
I was able to find and fix the root of the problem (the return statement was given an expression when it shouldn't have).
c7b7369
to
9b1d651
Compare
lib/ClangImporter/ImportDecl.cpp
Outdated
result->setType(emptyTuple); | ||
|
||
auto ret = new (ctx) ReturnStmt(SourceLoc(), result, /*Implicit=*/true); | ||
auto ret = new (ctx) ReturnStmt(SourceLoc(), nullptr, /*Implicit=*/true); |
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.
I'm going to make separate PRs for this and the change to IRGen/GenBuiltin.cpp
with tests.
9b1d651
to
094e325
Compare
@gribozavr friendly ping. This PR no longer has any SILGen changes. |
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.
LGTM with suggested changes.
@@ -155,4 +155,12 @@ struct StructDeletedDestructor { | |||
~StructDeletedDestructor() = delete; | |||
}; | |||
|
|||
struct HasDestructor { |
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.
Could you use StructWithDestructor
instead?
~HasDestructor() {} | ||
}; | ||
|
||
struct HasMemberWithDestructor { |
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.
Could you use StructWithSubobjectDestructor
instead?
Any C++ type that isn't trivially copyable is now also not a trivial type. This will preserve the destructor (among other things).
094e325
to
13632d4
Compare
@swift-ci please smoke test and merge |
1 similar comment
@swift-ci please smoke test and merge |
let d = StructWithDestructor() | ||
} | ||
|
||
// Make sure that "HasMemberWithDestructor" is marked as non-trivial by checking |
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.
HasMemberWithDestructor
=> StructWithSubobjectDestructor
?
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.
@zoecarver ^^^
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.
Oops forgot about this. #33150.
Any C++ type that isn't trivially copyable is now also not a trivial type. This will preserve the destructor (among other things).