Skip to content

Commit b5459b4

Browse files
committed
[Async Refactoring] Placeholder dropped params in fallback case
Make sure to convert any references to parameters that get dropped in the fallback case to placeholders.
1 parent 2758e31 commit b5459b4

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

lib/IDE/Refactoring.cpp

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7248,10 +7248,9 @@ class AsyncConverter : private SourceEntityWalker {
72487248
AllBindings.append(SuccessBindings.begin(), SuccessBindings.end());
72497249
AllBindings.push_back(ErrParam);
72507250

7251-
// Don't do any unwrapping or placeholder replacement since all params
7252-
// are still valid in the fallback case
72537251
prepareNames(ClassifiedBlock(), AllBindings, InlinePatterns);
7254-
7252+
preparePlaceholdersAndUnwraps(HandlerDesc, CallbackParams,
7253+
PlaceholderMode::FALLBACK);
72557254
addFallbackVars(AllBindings, Blocks);
72567255
addDo();
72577256
addAwaitCall(CE, ArgList.ref(), Blocks.SuccessBlock, SuccessBindings,
@@ -7306,7 +7305,7 @@ class AsyncConverter : private SourceEntityWalker {
73067305

73077306
prepareNames(Blocks.SuccessBlock, SuccessBindings, InlinePatterns);
73087307
preparePlaceholdersAndUnwraps(HandlerDesc, CallbackParams,
7309-
/*Success=*/true);
7308+
PlaceholderMode::SUCCESS_BLOCK);
73107309

73117310
addAwaitCall(CE, ArgList.ref(), Blocks.SuccessBlock, SuccessBindings,
73127311
InlinePatterns, HandlerDesc, /*AddDeclarations=*/true);
@@ -7323,7 +7322,7 @@ class AsyncConverter : private SourceEntityWalker {
73237322
ErrInlinePatterns,
73247323
/*AddIfMissing=*/HandlerDesc.Type != HandlerType::RESULT);
73257324
preparePlaceholdersAndUnwraps(HandlerDesc, CallbackParams,
7326-
/*Success=*/false);
7325+
PlaceholderMode::ERROR_BLOCK);
73277326

73287327
addCatch(ErrOrResultParam);
73297328
convertNodes(Blocks.ErrorBlock.nodesToPrint());
@@ -7608,14 +7607,31 @@ class AsyncConverter : private SourceEntityWalker {
76087607
OS << tok::l_brace;
76097608
}
76107609

7610+
enum class PlaceholderMode {
7611+
SUCCESS_BLOCK, ERROR_BLOCK, FALLBACK
7612+
};
7613+
76117614
void preparePlaceholdersAndUnwraps(AsyncHandlerDesc HandlerDesc,
76127615
const ClosureCallbackParams &Params,
7613-
bool Success) {
7616+
PlaceholderMode Mode) {
7617+
// Params that have been dropped always need placeholdering.
7618+
for (auto *Param : Params.getAllParams()) {
7619+
if (!Params.hasBinding(Param))
7620+
Placeholders.insert(Param);
7621+
}
7622+
// For the fallback case, no other params need placeholdering, as they are
7623+
// all freely accessible in the fallback case.
7624+
if (Mode == PlaceholderMode::FALLBACK)
7625+
return;
7626+
76147627
switch (HandlerDesc.Type) {
76157628
case HandlerType::PARAMS: {
76167629
auto *ErrParam = Params.getErrParam();
76177630
auto SuccessParams = Params.getSuccessParams();
7618-
if (!Success) {
7631+
switch (Mode) {
7632+
case PlaceholderMode::FALLBACK:
7633+
llvm_unreachable("Already handled");
7634+
case PlaceholderMode::ERROR_BLOCK:
76197635
if (ErrParam) {
76207636
if (HandlerDesc.shouldUnwrap(ErrParam->getType())) {
76217637
Placeholders.insert(ErrParam);
@@ -7624,7 +7640,8 @@ class AsyncConverter : private SourceEntityWalker {
76247640
// Can't use success params in the error body
76257641
Placeholders.insert(SuccessParams.begin(), SuccessParams.end());
76267642
}
7627-
} else {
7643+
break;
7644+
case PlaceholderMode::SUCCESS_BLOCK:
76287645
for (auto *SuccessParam : SuccessParams) {
76297646
auto Ty = SuccessParam->getType();
76307647
if (HandlerDesc.shouldUnwrap(Ty)) {
@@ -7634,10 +7651,6 @@ class AsyncConverter : private SourceEntityWalker {
76347651
Placeholders.insert(SuccessParam);
76357652
}
76367653

7637-
// If the parameter doesn't have a binding, it needs placeholdering.
7638-
if (!Params.hasBinding(SuccessParam))
7639-
Placeholders.insert(SuccessParam);
7640-
76417654
// Void parameters get omitted where possible, so turn any reference
76427655
// into a placeholder, as its usage is unlikely what the user wants.
76437656
if (HandlerDesc.getSuccessParamAsyncReturnType(Ty)->isVoid())
@@ -7646,6 +7659,7 @@ class AsyncConverter : private SourceEntityWalker {
76467659
// Can't use the error param in the success body
76477660
if (ErrParam)
76487661
Placeholders.insert(ErrParam);
7662+
break;
76497663
}
76507664
break;
76517665
}

test/refactoring/ConvertAsync/convert_bool.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,4 +459,21 @@ func testConvertBool() async throws {
459459
// OBJC-BOOL-WITH-ERR2-NEXT: print("neat")
460460
// OBJC-BOOL-WITH-ERR2-NEXT: print("neato")
461461
// OBJC-BOOL-WITH-ERR2-NEXT: }
462+
463+
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 -I %S/Inputs -I %t -target %target-triple %clang-importer-sdk-nosource | %FileCheck -check-prefix=OBJC-BOOL-WITH-ERR-FALLBACK %s
464+
ClassWithHandlerMethods.firstBoolFlagSuccess("") { str, success, unrelated, err in
465+
guard success && success == .random() else { fatalError() }
466+
print("much success", unrelated, str)
467+
}
468+
// OBJC-BOOL-WITH-ERR-FALLBACK: var str: String? = nil
469+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: var unrelated: Bool? = nil
470+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: var err: Error? = nil
471+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: do {
472+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: (str, unrelated) = try await ClassWithHandlerMethods.firstBoolFlagSuccess("")
473+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: } catch {
474+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: err = error
475+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: }
476+
// OBJC-BOOL-WITH-ERR-FALLBACK-EMPTY:
477+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: guard <#success#> && <#success#> == .random() else { fatalError() }
478+
// OBJC-BOOL-WITH-ERR-FALLBACK-NEXT: print("much success", unrelated, str)
462479
}

0 commit comments

Comments
 (0)