From 3879a47b52c713fc1a7d5a94b1e42515785c0ac4 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 4 Aug 2025 00:17:26 -0700 Subject: [PATCH] [CSSyntacticElement] Remove an assert that is too strict `return` statement withot an expression automatically gets an implicit `()` which is allowed to be converted to types like `()?` and `Any` or `Any?`. Let's remove a too strict assertion that expected a contextual type to always be `()?` even through in reality any type that `()` is convertible to is valid. Resolves: rdar://152553143 --- lib/Sema/CSSyntacticElement.cpp | 12 ++++------ test/Constraints/closures.swift | 23 +++++++++++++++++++ .../624dafcf406667e8.swift | 2 +- 3 files changed, 28 insertions(+), 9 deletions(-) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/624dafcf406667e8.swift (76%) diff --git a/lib/Sema/CSSyntacticElement.cpp b/lib/Sema/CSSyntacticElement.cpp index 4ff15d8398b45..3e1c226bffe5f 100644 --- a/lib/Sema/CSSyntacticElement.cpp +++ b/lib/Sema/CSSyntacticElement.cpp @@ -2159,14 +2159,10 @@ class SyntacticElementSolutionApplication if (resultType->isVoid()) return returnStmt; - // It's possible to infer e.g. `Void?` for cases where - // `return` doesn't have an expression. If contextual - // type is `Void` wrapped into N optional types, let's - // add an implicit `()` expression and let it be injected - // into optional required number of times. - - assert(resultType->getOptionalObjectType() && - resultType->lookThroughAllOptionalTypes()->isVoid()); + // Constraint generation injects an implicit `()` expresion + // into return statements without one. This helps to match + // cases like `Void` and `Any` that could be wrapped into a + // number of optional types. auto target = *cs.getTargetFor(returnStmt); returnStmt->setResult(target.getAsExpr()); diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift index 8089452e6b204..845c25920bcde 100644 --- a/test/Constraints/closures.swift +++ b/test/Constraints/closures.swift @@ -1392,3 +1392,26 @@ func test_generic_closure_parameter_requirement_failure( Container(data: { (input: TestInput) in payload(input.value) }) // expected-error@-1 {{generic struct 'TestInput' requires that 'Item.ID' conform to 'Collection'}} } + +// Since implicit result implies `()` it should be allowed to be converted to e.g. `Void` and `Any` +func test_implicit_result_conversions() { + func test_optional(_ x: Int) { + let _: Any? = { + switch x { + case 0: + return 1 + default: + return + } + }() + } + + func testAny(_: () -> Any) {} + + testAny { } // Ok + testAny { return } // Ok + testAny { + _ = 42 + return // Ok + } +} diff --git a/validation-test/compiler_crashers_2/624dafcf406667e8.swift b/validation-test/compiler_crashers_2_fixed/624dafcf406667e8.swift similarity index 76% rename from validation-test/compiler_crashers_2/624dafcf406667e8.swift rename to validation-test/compiler_crashers_2_fixed/624dafcf406667e8.swift index 8f4a7dcfb8f4e..7c68d69e696ba 100644 --- a/validation-test/compiler_crashers_2/624dafcf406667e8.swift +++ b/validation-test/compiler_crashers_2_fixed/624dafcf406667e8.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"(anonymous namespace)::SyntacticElementSolutionApplication::visitReturnStmt(swift::ReturnStmt*)"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s enum a func b(c : a) { let: ()->Copyable = { c return