Skip to content

Commit eebad26

Browse files
hamishknightbnbarham
authored andcommitted
[Async Refactoring] Add @discardableResult for defaulted completion
If the completion handler parameter has a default argument, mark the resulting async function as `@discardableResult`, as the caller may not care about the result. rdar://79190170
1 parent 5190907 commit eebad26

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

lib/IDE/Refactoring.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4422,6 +4422,14 @@ struct AsyncHandlerParamDesc : public AsyncHandlerDesc {
44224422
OS << tok::r_paren;
44234423
}
44244424

4425+
/// Retrieves the parameter decl for the completion handler parameter, or
4426+
/// \c nullptr if no valid completion parameter is present.
4427+
const ParamDecl *getHandlerParam() const {
4428+
if (!isValid())
4429+
return nullptr;
4430+
return Func->getParameters()->get(Index);
4431+
}
4432+
44254433
bool operator==(const AsyncHandlerParamDesc &Other) const {
44264434
return Handler == Other.Handler && Type == Other.Type &&
44274435
HasError == Other.HasError && Index == Other.Index;
@@ -6292,6 +6300,13 @@ class AsyncConverter : private SourceEntityWalker {
62926300

62936301
void addFuncDecl(const FuncDecl *FD) {
62946302
auto *Params = FD->getParameters();
6303+
auto *HandlerParam = TopHandler.getHandlerParam();
6304+
6305+
// If the completion handler parameter has a default argument, the async
6306+
// version is effectively @discardableResult, as not all the callers care
6307+
// about receiving the completion call.
6308+
if (HandlerParam && HandlerParam->isDefaultArgument())
6309+
OS << tok::at_sign << "discardableResult" << "\n";
62956310

62966311
// First chunk: start -> the parameter to remove (if any)
62976312
SourceLoc LeftEndLoc = Params->getLParenLoc().getAdvancedLoc(1);

test/refactoring/ConvertAsync/convert_function.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// RUN: %empty-directory(%t)
2+
13
enum CustomError : Error {
24
case Bad
35
}
@@ -309,3 +311,21 @@ func rdar78693050(_ completion: () -> Void) {
309311
// RDAR78693050-NEXT: }
310312
// RDAR78693050-NEXT: return
311313
// RDAR78693050-NEXT: }
314+
315+
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DISCARDABLE-RESULT %s
316+
func withDefaultedCompletion(arg: String, completion: @escaping (String) -> Void = {_ in}) {
317+
completion(arg)
318+
}
319+
320+
// DISCARDABLE-RESULT: @discardableResult
321+
// DISCARDABLE-RESULT-NEXT: func withDefaultedCompletion(arg: String) async -> String {
322+
// DISCARDABLE-RESULT-NEXT: return arg
323+
// DISCARDABLE-RESULT-NEXT: }
324+
325+
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DEFAULT-ARG %s
326+
func withDefaultArg(x: String = "") {
327+
}
328+
329+
// DEFAULT-ARG: convert_function.swift [[# @LINE-3]]:1 -> [[# @LINE-2]]:2
330+
// DEFAULT-ARG-NOT: @discardableResult
331+
// DEFAULT-ARG-NEXT: {{^}}func withDefaultArg(x: String = "") async

0 commit comments

Comments
 (0)