Introduce 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.
This commit is contained in:
Hamish Knight
2023-02-01 15:30:18 +00:00
parent df2b3b2880
commit a40f1abaff
70 changed files with 5520 additions and 188 deletions

View File

@@ -738,6 +738,7 @@ Optional<Diag<Type, Type>> GenericArgumentsMismatchFailure::getDiagnosticFor(
case CTP_CalleeResult:
case CTP_EnumCaseRawValue:
case CTP_ExprPattern:
case CTP_SingleValueStmtBranch:
break;
}
return None;
@@ -2488,7 +2489,10 @@ bool ContextualFailure::diagnoseAsError() {
diagnostic = diag::ternary_expr_cases_mismatch;
break;
}
case ConstraintLocator::SingleValueStmtBranch: {
diagnostic = diag::single_value_stmt_branches_mismatch;
break;
}
case ConstraintLocator::ContextualType: {
if (diagnoseConversionToBool())
return true;
@@ -2688,6 +2692,7 @@ getContextualNilDiagnostic(ContextualTypePurpose CTP) {
case CTP_WrappedProperty:
case CTP_ComposedPropertyWrapper:
case CTP_ExprPattern:
case CTP_SingleValueStmtBranch:
return None;
case CTP_EnumCaseRawValue:
@@ -3442,6 +3447,9 @@ ContextualFailure::getDiagnosticFor(ContextualTypePurpose context,
case CTP_WrappedProperty:
return diag::wrapped_value_mismatch;
case CTP_SingleValueStmtBranch:
return diag::cannot_convert_initializer_value;
case CTP_CaseStmt:
case CTP_ThrowStmt:
case CTP_ForEachStmt: