Skip to content

Commit 1ebb1fd

Browse files
committed
[Async Refactoring] Add parens around custom error cast
When passing a forwarded error to a CustomError? completion handler parameter, wrap the cast in a set of parentheses to silence a warning in the refactored code. rdar://80409905
1 parent 72909bd commit 1ebb1fd

File tree

3 files changed

+30
-16
lines changed

3 files changed

+30
-16
lines changed

Diff for: lib/IDE/Refactoring.cpp

+27-13
Original file line numberDiff line numberDiff line change
@@ -7596,17 +7596,32 @@ class AsyncConverter : private SourceEntityWalker {
75967596
OS << tok::r_paren;
75977597
}
75987598

7599-
/// If the error type of \p HandlerDesc is more specialized than \c Error,
7600-
/// adds an 'as! CustomError' cast to the more specialized error type to the
7601-
/// output stream.
7602-
void
7603-
addCastToCustomErrorTypeIfNecessary(const AsyncHandlerDesc &HandlerDesc) {
7604-
const ASTContext &Ctx = HandlerDesc.getHandler()->getASTContext();
7599+
/// Adds a forwarded error argument to a completion handler call. If the error
7600+
/// type of \p HandlerDesc is more specialized than \c Error, an
7601+
/// 'as! CustomError' cast to the more specialized error type will be added to
7602+
/// the output stream.
7603+
void addForwardedErrorArgument(StringRef ErrorName,
7604+
const AsyncHandlerDesc &HandlerDesc) {
7605+
// If the error type is already Error, we can pass it as-is.
76057606
auto ErrorType = *HandlerDesc.getErrorType();
7606-
if (ErrorType->getCanonicalType() != Ctx.getExceptionType()) {
7607-
OS << " " << tok::kw_as << tok::exclaim_postfix << " ";
7608-
ErrorType->lookThroughSingleOptionalType()->print(OS);
7607+
if (ErrorType->getCanonicalType() == getASTContext().getExceptionType()) {
7608+
OS << ErrorName;
7609+
return;
76097610
}
7611+
7612+
// Otherwise we need to add a force cast to the destination custom error
7613+
// type. If this is for an Error? parameter, we'll need to add parens around
7614+
// the cast to silence a compiler warning about force casting never
7615+
// producing nil.
7616+
auto RequiresParens = HandlerDesc.getErrorParam().hasValue();
7617+
if (RequiresParens)
7618+
OS << tok::l_paren;
7619+
7620+
OS << ErrorName << " " << tok::kw_as << tok::exclaim_postfix << " ";
7621+
ErrorType->lookThroughSingleOptionalType()->print(OS);
7622+
7623+
if (RequiresParens)
7624+
OS << tok::r_paren;
76107625
}
76117626

76127627
/// If \p T has a natural default value like \c nil for \c Optional or \c ()
@@ -7637,8 +7652,7 @@ class AsyncConverter : private SourceEntityWalker {
76377652
if (HandlerDesc.HasError && Index == HandlerDesc.params().size() - 1) {
76387653
// The error parameter is the last argument of the completion handler.
76397654
if (ResultName.empty()) {
7640-
OS << "error";
7641-
addCastToCustomErrorTypeIfNecessary(HandlerDesc);
7655+
addForwardedErrorArgument("error", HandlerDesc);
76427656
} else {
76437657
addDefaultValueOrPlaceholder(HandlerDesc.params()[Index].getPlainType());
76447658
}
@@ -7707,8 +7721,8 @@ class AsyncConverter : private SourceEntityWalker {
77077721
OS << tok::period_prefix << "success" << tok::l_paren << ResultName
77087722
<< tok::r_paren;
77097723
} else {
7710-
OS << tok::period_prefix << "failure" << tok::l_paren << "error";
7711-
addCastToCustomErrorTypeIfNecessary(HandlerDesc);
7724+
OS << tok::period_prefix << "failure" << tok::l_paren;
7725+
addForwardedErrorArgument("error", HandlerDesc);
77127726
OS << tok::r_paren;
77137727
}
77147728
break;

Diff for: test/refactoring/ConvertAsync/basic.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func customError(completion: (String?, CustomError?) -> Void) { }
133133
// ASYNC-CUSTOMERROR-NEXT: let result = try await customError()
134134
// ASYNC-CUSTOMERROR-NEXT: completion(result, nil)
135135
// ASYNC-CUSTOMERROR-NEXT: } catch {
136-
// ASYNC-CUSTOMERROR-NEXT: completion(nil, error as! CustomError)
136+
// ASYNC-CUSTOMERROR-NEXT: completion(nil, (error as! CustomError))
137137
// ASYNC-CUSTOMERROR-NEXT: }
138138
// ASYNC-CUSTOMERROR-NEXT: }
139139
// ASYNC-CUSTOMERROR-NEXT: }
@@ -308,7 +308,7 @@ func genericError<E>(completion: (String?, E?) -> Void) where E: Error { }
308308
// GENERIC-ERROR-NEXT: let result: String = try await genericError()
309309
// GENERIC-ERROR-NEXT: completion(result, nil)
310310
// GENERIC-ERROR-NEXT: } catch {
311-
// GENERIC-ERROR-NEXT: completion(nil, error as! E)
311+
// GENERIC-ERROR-NEXT: completion(nil, (error as! E))
312312
// GENERIC-ERROR-NEXT: }
313313
// GENERIC-ERROR-NEXT: }
314314
// GENERIC-ERROR-NEXT: }

Diff for: test/refactoring/ConvertAsync/variable_as_callback.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ func testGenericErrorVariableCompletionHandler<MyGenericError>(completionHandler
317317
// GENERIC-ERROR-NEXT: let result: String = try await genericError()
318318
// GENERIC-ERROR-NEXT: completionHandler(result, nil)
319319
// GENERIC-ERROR-NEXT: } catch {
320-
// GENERIC-ERROR-NEXT: completionHandler(nil, error as! MyGenericError)
320+
// GENERIC-ERROR-NEXT: completionHandler(nil, (error as! MyGenericError))
321321
// GENERIC-ERROR-NEXT: }
322322

323323
// RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+2):1 | %FileCheck -check-prefix=DEFAULT-ARGS-FUNC %s

0 commit comments

Comments
 (0)