Skip to content

Commit 1007cc9

Browse files
authored
Merge pull request #38911 from jckarter/async-let-throw-completion-order
Concurrency: Don't rely on future wait context in asyncLet_finish.
2 parents 4e08643 + 745467d commit 1007cc9

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

stdlib/public/Concurrency/AsyncLet.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,13 @@ static void swift_asyncLet_getImpl(SWIFT_ASYNC_CONTEXT AsyncContext *callerConte
245245
}
246246

247247
struct AsyncLetContinuationContext: AsyncContext {
248-
AsyncLet *alet;
248+
AsyncLet *alet;
249+
OpaqueValue *resultBuffer;
249250
};
250251

252+
static_assert(sizeof(AsyncLetContinuationContext) <= sizeof(TaskFutureWaitAsyncContext),
253+
"compiler provides the same amount of context space to each");
254+
251255
SWIFT_CC(swiftasync)
252256
static void _asyncLet_get_throwing_continuation(
253257
SWIFT_ASYNC_CONTEXT AsyncContext *callContext,
@@ -369,8 +373,7 @@ static void _asyncLet_finish_continuation(
369373
auto continuationContext
370374
= reinterpret_cast<AsyncLetContinuationContext*>(callContext);
371375
auto alet = continuationContext->alet;
372-
auto resultBuffer = asImpl(alet)->getFutureContext()
373-
->successResultPointer;
376+
auto resultBuffer = continuationContext->resultBuffer;
374377

375378
// Destroy the error, or the result that was stored to the buffer.
376379
if (error) {
@@ -415,6 +418,7 @@ static void swift_asyncLet_finishImpl(SWIFT_ASYNC_CONTEXT AsyncContext *callerCo
415418
aletContext->Parent = callerContext;
416419
aletContext->ResumeParent = resumeFunction;
417420
aletContext->alet = alet;
421+
aletContext->resultBuffer = reinterpret_cast<OpaqueValue*>(resultBuffer);
418422
auto futureContext = asImpl(alet)->getFutureContext();
419423

420424
// TODO: It would be nice if we could await the future without having to
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// rdar://81481317
2+
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking %import-libdispatch -parse-as-library) | %FileCheck %s
3+
// REQUIRES: executable_test
4+
// REQUIRES: concurrency
5+
// REQUIRES: libdispatch
6+
struct Bad: Error {}
7+
8+
class Foo { init() async throws {}; deinit { print("Foo down") } }
9+
class Bar { init() async throws { throw Bad() }; deinit { print("Bar down") } }
10+
class Baz { init() async throws {}; deinit { print("Baz down") } }
11+
12+
func zim(y: Bar, x: Foo, z: Baz) { print("hooray") }
13+
14+
@main struct Butt {
15+
16+
static func main() async {
17+
do {
18+
async let x = Foo()
19+
async let y = Bar()
20+
async let z = Baz()
21+
22+
return try await zim(y: y, x: x, z: z)
23+
} catch {
24+
// CHECK: oopsie woopsie
25+
print("oopsie woopsie")
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)