Skip to content

[5.8] Introduce if/switch expressions #63378

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

Merged

Conversation

hamishknight
Copy link
Contributor

@hamishknight hamishknight commented Feb 2, 2023

5.8 cherry-pick of #63022


Introduce SingleValueStmtExpr, which allows the embedding of a statement in an expression context. This then allows us to parse and type-check if and switch statements as expressions. In the future, SingleValueStmtExpr could also be used for e.g do expressions.

For now, only single expression branches are supported for producing a value from an if/switch expression, and each branch is type-checked independently. A multi-statement branch may only appear if it ends with a throw, and it may not break, continue, or return.

The placement of if/switch expressions is also currently limited by a syntactic use diagnostic. Currently they're only allowed in bindings, assignments, throws, and returns. But this could be lifted in the future if desired.

xedin and others added 8 commits February 1, 2023 16:40
For a single expression closure, just use the
expression as the body in the case where we're
coercing to Void, as the return is already
implied. This avoids crashing in
`ClosureExpr::getSingleExpressionBody` with a
double braced body.

Surprisingly it seems nothing is currently calling
`ClosureExpr::getSingleExpressionBody` after
type-checking, so no test case, but later commits
in this patch will exercise this case.
Split out brace element handling for a couple of
walkers into a new function. The diff for this is
best viewed without whitespace changes. This
should be NFC.
Factor out some type-checking logic for ReturnStmt,
including the conversion to FailStmt, into a
request. We can then invoke this request from
both the regular type-checking path, as well as
during a pre-check of an expression.
Introduce SingleValueStmtExpr, which allows the
embedding of a statement in an expression context.
This then allows us to parse and type-check `if`
and `switch` statements as expressions, gated
behind the `IfSwitchExpression` experimental
feature for now. In the future,
SingleValueStmtExpr could also be used for e.g
`do` expressions.

For now, only single expression branches are
supported for producing a value from an
`if`/`switch` expression, and each branch is
type-checked independently. A multi-statement
branch may only appear if it ends with a `throw`,
and it may not `break`, `continue`, or `return`.

The placement of `if`/`switch` expressions is also
currently limited by a syntactic use diagnostic.
Currently they're only allowed in bindings,
assignments, throws, and returns. But this could
be lifted in the future if desired.
Look through `try`/`await` markers when looking for
out of place if/switch expressions, and customize
the effect checking diagnostic such that we error
that `try`/`await` are redundant on `if`/`switch`
expressions.
@hamishknight
Copy link
Contributor Author

@hamishknight
Copy link
Contributor Author

Currently we only consider ParamDecls, but isolated
conjunctions can reference external VarDecls too.

This fixes a spurious "cannot reference invalid declaration"
error when the result builder transform is disabled
in the test case rdar104687668.swift. It also fixes
the attached test case, where an if expression
references a pattern var in a for loop.

rdar://105080067
@hamishknight hamishknight requested a review from a team as a code owner February 6, 2023 14:35
@hamishknight
Copy link
Contributor Author

@hamishknight
Copy link
Contributor Author

🚢

@hamishknight hamishknight merged commit d78b035 into swiftlang:release/5.8 Feb 7, 2023
@hamishknight hamishknight deleted the express-yourself-5.8 branch February 7, 2023 16:55
amartini51 added a commit to amartini51/swift-book that referenced this pull request Feb 25, 2023
The test cases that exercise this feature include switches over a Bool
with just a true and false case.

    swiftlang/swift#63378

This just follows the principle from the rest of Swift that switches
must be exhaustive -- it's not a special case here -- which is probably
why the SE proposal doesn't call it out like it does for 'if'
expressions needing an 'else' clause.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍒 release cherry pick Flag: Release branch cherry picks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants