Skip to content

Commit 7ab5915

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 aa189f2 commit 7ab5915

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
@@ -4623,16 +4623,24 @@ class NodesToPrint {
46234623
!Nodes.back().isImplicit();
46244624
}
46254625

4626-
/// If the last recorded node is an explicit return or break statement, drop
4627-
/// it from the list.
4628-
void dropTrailingReturnOrBreak() {
4626+
/// If the last recorded node is an explicit return or break statement that
4627+
/// can be safely dropped, drop it from the list.
4628+
void dropTrailingReturnOrBreakIfPossible() {
46294629
if (!hasTrailingReturnOrBreak())
46304630
return;
46314631

4632+
auto *Node = Nodes.back().get<Stmt *>();
4633+
4634+
// If this is a return statement with return expression, let's preserve it.
4635+
if (auto *RS = dyn_cast<ReturnStmt>(Node)) {
4636+
if (RS->hasResult())
4637+
return;
4638+
}
4639+
46324640
// Remove the node from the list, but make sure to add it as a possible
46334641
// comment loc to preserve any of its attached comments.
4634-
auto Node = Nodes.pop_back_val();
4635-
addPossibleCommentLoc(Node.getStartLoc());
4642+
Nodes.pop_back();
4643+
addPossibleCommentLoc(Node->getStartLoc());
46364644
}
46374645

46384646
/// Returns a list of nodes to print in a brace statement. This picks up the
@@ -4895,7 +4903,7 @@ struct CallbackClassifier {
48954903
NodesToPrint Nodes) {
48964904
if (Nodes.hasTrailingReturnOrBreak()) {
48974905
CurrentBlock = OtherBlock;
4898-
Nodes.dropTrailingReturnOrBreak();
4906+
Nodes.dropTrailingReturnOrBreakIfPossible();
48994907
Block->addAllNodes(std::move(Nodes));
49004908
} else {
49014909
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)