-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Sema: Implicit conversion for single-expression closures of Never type (3.0) #4951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sema: Implicit conversion for single-expression closures of Never type (3.0) #4951
Conversation
@swift-ci Please test |
Build failed |
This fixes a usability regression with the removal of @NoReturn in Swift 3. Previously, it was legal to write this: let callback: () -> Int = { fatalError() } Now that the special @NoReturn attribute has been replaced with a Never type, the above fails to typecheck, because the expression now has type 'Never', and we expect a value of type 'Int'. Getting around this behavior requires ugly workarounds to force the parser to treat the body as a statement rather than an expression; for example, let callback: () -> Int = { _ = (); fatalError() } This patch generalized single-expression closures to allow the 'Never to T' conversion. Note that this is rather narrow in scope -- it only applies to closure *literals*, single-expression ones at that, not arbitrary function *values*. In fact, it is not really a conversion at all, but more of a desugaring rule for single-expression closures. They can now be summarized as follows: - If the closure literal has contextual return type T and the expression has Never type, the closure desugars as { _ = <expr> }, with no ReturnStmt. - If the closure literal has contextual return type T for some non-void type T, the closure desugars as { return <expr> }; the expression type must be convertible to T. - If the closure literal has contextual return type Void, and the expression has some non-Void type T, the closure desugars as { _ = <expr>; return () }. Fixes <rdar://problem/28269358> and <https://bugs.swift.org/browse/SR-2661>.
e680e4d
to
3b137b2
Compare
@swift-ci Please test |
1 similar comment
@swift-ci Please test |
SmallVector<ASTNode, 1> elements; | ||
elements.push_back(singleExpr); | ||
|
||
auto braceStmt = BraceStmt::create(tc.Context, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This kind of AST hackery feels gross, but... okay. I don't see a better localized fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just copy and pasted from the old code (and I know, that's a HORRIBLE excuse)
[pull] swiftwasm from main
Never
return type, we lost a bit of functionality. Since Never is just an ordinary type, the type checker did not allow a single-expression closure to contain a Never-returning expression unless the closure type itself returned Never. This precludes using single expression closures for callbacks in certain situations. This patch adds a new rule, similar to the existing rule for dropping the return type of a single-expression closure.