Move out-of-place SingleValueStmtExpr checking into
`performSyntacticExprDiagnostics`, to ensure we
catch all expressions. Previously we did the walk
as a part of Decl-based MiscDiagnostics, but it
turns out that can miss expressions in property
initializers, subscript default arguments, and
custom attrs.
This does mean that we'll now no longer diagnose
out-of-place if/switch exprs if the expression
didn't type-check, but that's consistent with the
rest of MiscDiagnostics, and I don't think it will
be a major issue in practice. We probably ought to
consider moving this checking into PreCheckExpr,
but that would require first separating out
SequenceExpr folding, which has other consequences,
and so I'm leaving as future work for now.
Previously we would only look through a handful of
AST node types when determining if an if/switch
expression is in a valid position. However this
doesn't handle cases where we synthesize code
around an if/switch expression, such as
`init(erasing:)` calls. As such, relax the logic
such that it can look through any implicit
expression.
rdar://113435870
- Allow an if/switch expression to become an
implicit return of a function that has a `#if`
body with a single active element that is an `if`
or `switch`.
- Allow `#if` branches of an if/switch expression,
as long as there is a single active expression
element.
rdar://107487977
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.
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.