Skip to content

Commit cd3e96a

Browse files
committed
[Sema]: fix @discardableResult interaction with implicit @sendable conversions
Updates existing diagnostic handling to look through function conversions when suppressing diagnostics for unused functions that are return values from callees marked with @discardableResult.
1 parent 8a689bb commit cd3e96a

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1886,7 +1886,26 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
18861886
: valueE;
18871887

18881888
if (auto *Fn = dyn_cast<ApplyExpr>(expr)) {
1889-
if (auto *calledValue = Fn->getCalledValue()) {
1889+
/// Some concurrency-related things may have intermediate conversions that
1890+
/// we want to look through, e.g.
1891+
///
1892+
/// ```swift
1893+
/// @discardableResult
1894+
/// @MainActor
1895+
/// func foo() -> () -> Void {
1896+
/// return {}
1897+
/// }
1898+
///
1899+
/// @MainActor
1900+
/// func test() {
1901+
/// foo()
1902+
/// // ^ return value implicitly wapped in a `@Sendable` conversion
1903+
/// }
1904+
/// ```
1905+
/// Attempt to look through function conversions when resolving the
1906+
/// called value.
1907+
if (auto *calledValue =
1908+
Fn->getCalledValue(/*skipFunctionConversions=*/true)) {
18901909
if (auto *FD = dyn_cast<AbstractFunctionDecl>(calledValue)) {
18911910
if (FD->getAttrs().hasAttribute<DiscardableResultAttr>()) {
18921911
isDiscardable = true;

test/Concurrency/attr_discardableResult_async_await.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,23 @@ func mainActorAsyncDiscardable() async -> Int { 0 }
1414
func consumesMainActorAsyncDiscardable() async {
1515
await mainActorAsyncDiscardable() // ok
1616
}
17+
18+
// https://github.com/swiftlang/swift/issues/83463
19+
20+
@MainActor
21+
@discardableResult
22+
func returnsDiscardableFunc() -> () -> Void { return {} }
23+
24+
@MainActor
25+
func testDiscardsSyncFuncWithImplicitSendableConversion() {
26+
returnsDiscardableFunc()
27+
}
28+
29+
@MainActor
30+
@discardableResult
31+
func mainActorAsyncReturnsDiscardableFunc() async -> () -> Void { return {} }
32+
33+
@MainActor
34+
func discardsAsyncFuncWithImplicitSendableConversion() async {
35+
await mainActorAsyncReturnsDiscardableFunc()
36+
}

0 commit comments

Comments
 (0)