mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Concurrency] Implicitly strip optionals for return type of translated "async throws".
Review over a large number of APIs has found that most of the time, the result type of an Objective-C completion handler method that becomes "async throws" should be optional. Change the default behavior to match this, and replace _Nullable_on_error with _Nullable_result to capture the case where the result should be optional.
This commit is contained in:
@@ -2065,7 +2065,13 @@ static Type decomposeCompletionHandlerType(
|
||||
paramIdx == *info.completionHandlerErrorParamIndex())
|
||||
continue;
|
||||
|
||||
resultTypeElts.push_back(param.getPlainType());
|
||||
// If there is an error parameter, remove nullability.
|
||||
Type paramType = param.getPlainType();
|
||||
// TODO: Clang should gain a nullability form that overrides this.
|
||||
if (info.completionHandlerErrorParamIndex())
|
||||
paramType = paramType->lookThroughAllOptionalTypes();
|
||||
|
||||
resultTypeElts.push_back(paramType);
|
||||
}
|
||||
|
||||
switch (resultTypeElts.size()) {
|
||||
|
||||
@@ -1946,8 +1946,10 @@ bool swift::fixDeclarationName(InFlightDiagnostic &diag, const ValueDecl *decl,
|
||||
}
|
||||
|
||||
// Fix the argument names that need fixing.
|
||||
assert(name.getArgumentNames().size()
|
||||
== targetName.getArgumentNames().size());
|
||||
if (name.getArgumentNames().size()
|
||||
!= targetName.getArgumentNames().size())
|
||||
return false;
|
||||
|
||||
auto params = func->getParameters();
|
||||
for (unsigned i = 0, n = name.getArgumentNames().size(); i != n; ++i) {
|
||||
auto origArg = name.getArgumentNames()[i];
|
||||
|
||||
@@ -8,8 +8,8 @@ import ObjCConcurrency
|
||||
func testSlowServer(slowServer: SlowServer) async throws {
|
||||
let _: Int = await slowServer.doSomethingSlow("mail")
|
||||
let _: Bool = await slowServer.checkAvailability()
|
||||
let _: String = try await slowServer.findAnswer() ?? "nope"
|
||||
let _: String = await try slowServer.findAnswerFailingly() ?? "nope"
|
||||
let _: String = try await slowServer.findAnswer()
|
||||
let _: String = await try slowServer.findAnswerFailingly()
|
||||
let _: Void = await slowServer.doSomethingFun("jump")
|
||||
let _: (Int) -> Void = slowServer.completionHandler
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
// CHECK-DAG: func doSomethingSlow(_ operation: String, completionHandler handler: @escaping (Int) -> Void)
|
||||
// CHECK-DAG: func doSomethingSlow(_ operation: String) async -> Int
|
||||
// CHECK-DAG: func doSomethingDangerous(_ operation: String, completionHandler handler: ((String?, Error?) -> Void)? = nil)
|
||||
// CHECK-DAG: func doSomethingDangerous(_ operation: String) async throws -> String?
|
||||
// CHECK-DAG: func doSomethingDangerous(_ operation: String) async throws -> String
|
||||
// CHECK-DAG: func checkAvailability(completionHandler: @escaping (Bool) -> Void)
|
||||
// CHECK-DAG: func checkAvailability() async -> Bool
|
||||
// CHECK-DAG: func findAnswer(completionHandler handler: @escaping (String?, Error?) -> Void)
|
||||
// CHECK-DAG: func findAnswer() async throws -> String?
|
||||
// CHECK-DAG: func findAnswer() async throws -> String
|
||||
// CHECK-DAG: func findAnswerFailingly(completionHandler handler: @escaping (String?, Error?) -> Void) throws
|
||||
// CHECK-DAG: func findAnswerFailingly() async throws -> String?
|
||||
// CHECK-DAG: func findAnswerFailingly() async throws -> String
|
||||
// CHECK-DAG: func doSomethingFun(_ operation: String) async
|
||||
// CHECK: {{^[}]$}}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import ObjCConcurrency
|
||||
|
||||
// Conform via async method
|
||||
class C1: ConcurrentProtocol {
|
||||
func askUser(toSolvePuzzle puzzle: String) async throws -> String? { nil }
|
||||
func askUser(toSolvePuzzle puzzle: String) async throws -> String { "" }
|
||||
|
||||
func askUser(toJumpThroughHoop hoop: String) async -> String { "hello" }
|
||||
}
|
||||
@@ -26,7 +26,7 @@ class C2: ConcurrentProtocol {
|
||||
// Conform via both; this is an error
|
||||
class C3: ConcurrentProtocol {
|
||||
// expected-note@+1{{method 'askUser(toSolvePuzzle:)' declared here}}
|
||||
func askUser(toSolvePuzzle puzzle: String) async throws -> String? { nil }
|
||||
func askUser(toSolvePuzzle puzzle: String) async throws -> String { "" }
|
||||
|
||||
// expected-error@+1{{'askUser(toSolvePuzzle:completionHandler:)' with Objective-C selector 'askUserToSolvePuzzle:completionHandler:' conflicts with method 'askUser(toSolvePuzzle:)' with the same Objective-C selector}}
|
||||
func askUser(toSolvePuzzle puzzle: String, completionHandler: ((String?, Error?) -> Void)?) {
|
||||
|
||||
Reference in New Issue
Block a user