-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RFC] Perform lifetime bound checks for arguments to coroutine #69360
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
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
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.
Thanks for bringing this! I didn't notice the post in discourse and I'll put higher level comments there.
|
||
Co<int> bar_coro(const int &b, int c) { | ||
int x = co_await foo_coro(b); | ||
int y = co_await foo_coro(1); |
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.
How is this implemented? I mean how can we don't emit warnings to co_await foo_coro(1)
but emit warnings to auto unsafe1 = foo_coro(1);
? This is not showed in this patch itself.
I envision the reason may be that we will copy the parameters at the beginning of the coroutines. If it is indeed the reason, then it smells bad. Since the behavior depends that behavior implicitly.
For example, the behavior of co_await foo_coro();
depends on the implementation of the corresponding awaiter. It is completely possible that co_await foo_coro();
doing exactly the same thing with a standalone foo_coro();
. But we may emit warnings for one place but not the other one.
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.
This is because co_await
expr is equivalent to auto x = SomeFunc(foo_coro(1));
(func
is await_transform
for co_await
).
This is safe because temporary lives as long as the SomeFunc
call. This same reasoning can be applied to co_await
as the temporary lives in the coroutine frame as long as the coroutine co_await
s.
The only implementation of awaiter that could be problematic and go undetected is when it schedules the foo_coro
on another thread and resumes the awaiting coroutine before foo_coro
is finished.
RD->getUnderlyingDecl()->specific_attrs<clang::AnnotateAttr>()) { | ||
// Only for demonstration: Get feedback and add a clang annotation as an | ||
// extension. | ||
if (attr->getAnnotation() == "coro_type") { |
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 don't think you need this to find if a record is a "coroutine type", there are other ways, for example:
if (rec->getDeclName().isIdentifier() && rec->getName() == "promise_type") {
....
This idea was introduced in RFC: Lifetime bound checks for parameters of coroutine
The plan here is to gather comments, and if the direction looks good, then introduce a formal clang annotation
clang::lifetimebound_coroutine
as part of this change.