Skip to content

Commit 83337e0

Browse files
committed
[Refactoring] Don't drop returns with expressions
Previously we were unconditionally dropping a return statement if it was the last node, which could cause us to inadvertently drop the result expression as well. Instead, only drop bare 'return' statements. rdar://77789360
1 parent 204898a commit 83337e0

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

lib/IDE/Refactoring.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4631,16 +4631,24 @@ class NodesToPrint {
46314631
!Nodes.back().isImplicit();
46324632
}
46334633

4634-
/// If the last recorded node is an explicit return or break statement, drop
4635-
/// it from the list.
4636-
void dropTrailingReturnOrBreak() {
4634+
/// If the last recorded node is an explicit return or break statement that
4635+
/// can be safely dropped, drop it from the list.
4636+
void dropTrailingReturnOrBreakIfPossible() {
46374637
if (!hasTrailingReturnOrBreak())
46384638
return;
46394639

4640+
auto *Node = Nodes.back().get<Stmt *>();
4641+
4642+
// If this is a return statement with return expression, let's preserve it.
4643+
if (auto *RS = dyn_cast<ReturnStmt>(Node)) {
4644+
if (RS->hasResult())
4645+
return;
4646+
}
4647+
46404648
// Remove the node from the list, but make sure to add it as a possible
46414649
// comment loc to preserve any of its attached comments.
4642-
auto Node = Nodes.pop_back_val();
4643-
addPossibleCommentLoc(Node.getStartLoc());
4650+
Nodes.pop_back();
4651+
addPossibleCommentLoc(Node->getStartLoc());
46444652
}
46454653

46464654
/// Returns a list of nodes to print in a brace statement. This picks up the
@@ -4903,7 +4911,7 @@ struct CallbackClassifier {
49034911
NodesToPrint Nodes) {
49044912
if (Nodes.hasTrailingReturnOrBreak()) {
49054913
CurrentBlock = OtherBlock;
4906-
Nodes.dropTrailingReturnOrBreak();
4914+
Nodes.dropTrailingReturnOrBreakIfPossible();
49074915
Block->addAllNodes(std::move(Nodes));
49084916
} else {
49094917
Block->addAllNodes(std::move(Nodes));

test/refactoring/ConvertAsync/convert_function.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,26 @@ func testReturnHandling(_ completion: (String?, Error?) -> Void) {
257257
// RETURN-HANDLING-NEXT: {{^}} return ""{{$}}
258258
// RETURN-HANDLING-NEXT: }
259259

260+
// rdar://77789360 Make sure we don't print a double return statement and don't
261+
// completely drop completion(a).
262+
// RUN: %refactor -add-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RETURN-HANDLING2 %s
263+
func testReturnHandling2(completion: @escaping (String) -> ()) {
264+
testReturnHandling { x, err in
265+
guard let x = x else {
266+
let a = ""
267+
return completion(a)
268+
}
269+
let b = ""
270+
return completion(b)
271+
}
272+
}
273+
// RETURN-HANDLING2: func testReturnHandling2() async -> String {
274+
// RETURN-HANDLING2-NEXT: do {
275+
// RETURN-HANDLING2-NEXT: let x = try await testReturnHandling()
276+
// RETURN-HANDLING2-NEXT: let b = ""
277+
// RETURN-HANDLING2-NEXT: {{^}}<#return#> b{{$}}
278+
// RETURN-HANDLING2-NEXT: } catch let err {
279+
// RETURN-HANDLING2-NEXT: let a = ""
280+
// RETURN-HANDLING2-NEXT: {{^}}<#return#> a{{$}}
281+
// RETURN-HANDLING2-NEXT: }
282+
// RETURN-HANDLING2-NEXT: }

0 commit comments

Comments
 (0)