mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -1961,12 +1961,19 @@ private:
|
||||
/// type-checked.
|
||||
DeclContext *dc;
|
||||
|
||||
// TODO: Fold the 3 below fields into ContextualTypeInfo
|
||||
|
||||
/// The purpose of the contextual type.
|
||||
ContextualTypePurpose contextualPurpose;
|
||||
|
||||
/// The type to which the expression should be converted.
|
||||
TypeLoc convertType;
|
||||
|
||||
/// The locator for the contextual type conversion constraint, or
|
||||
/// \c nullptr to use the default locator which is anchored directly on
|
||||
/// the expression.
|
||||
ConstraintLocator *convertTypeLocator;
|
||||
|
||||
/// When initializing a pattern from the expression, this is the
|
||||
/// pattern.
|
||||
Pattern *pattern;
|
||||
@@ -2054,14 +2061,25 @@ private:
|
||||
public:
|
||||
SolutionApplicationTarget(Expr *expr, DeclContext *dc,
|
||||
ContextualTypePurpose contextualPurpose,
|
||||
Type convertType, bool isDiscarded)
|
||||
Type convertType,
|
||||
ConstraintLocator *convertTypeLocator,
|
||||
bool isDiscarded)
|
||||
: SolutionApplicationTarget(expr, dc, contextualPurpose,
|
||||
TypeLoc::withoutLoc(convertType),
|
||||
isDiscarded) { }
|
||||
convertTypeLocator, isDiscarded) {}
|
||||
|
||||
SolutionApplicationTarget(Expr *expr, DeclContext *dc,
|
||||
ContextualTypePurpose contextualPurpose,
|
||||
TypeLoc convertType, bool isDiscarded);
|
||||
Type convertType, bool isDiscarded)
|
||||
: SolutionApplicationTarget(expr, dc, contextualPurpose, convertType,
|
||||
/*convertTypeLocator*/ nullptr, isDiscarded) {
|
||||
}
|
||||
|
||||
SolutionApplicationTarget(Expr *expr, DeclContext *dc,
|
||||
ContextualTypePurpose contextualPurpose,
|
||||
TypeLoc convertType,
|
||||
ConstraintLocator *convertTypeLocator,
|
||||
bool isDiscarded);
|
||||
|
||||
SolutionApplicationTarget(Expr *expr, DeclContext *dc, ExprPattern *pattern,
|
||||
Type patternType)
|
||||
@@ -2288,6 +2306,13 @@ public:
|
||||
return getExprContextualType();
|
||||
}
|
||||
|
||||
/// Retrieve the conversion type locator for the expression, or \c nullptr
|
||||
/// if it has not been set.
|
||||
ConstraintLocator *getExprConvertTypeLocator() const {
|
||||
assert(kind == Kind::expression);
|
||||
return expression.convertTypeLocator;
|
||||
}
|
||||
|
||||
/// Returns the autoclosure parameter type, or \c nullptr if the
|
||||
/// expression has a different kind of context.
|
||||
FunctionType *getAsAutoclosureParamType() const {
|
||||
@@ -4224,7 +4249,8 @@ public:
|
||||
|
||||
/// Add the appropriate constraint for a contextual conversion.
|
||||
void addContextualConversionConstraint(Expr *expr, Type conversionType,
|
||||
ContextualTypePurpose purpose);
|
||||
ContextualTypePurpose purpose,
|
||||
ConstraintLocator *locator);
|
||||
|
||||
/// Convenience function to pass an \c ArrayRef to \c addJoinConstraint
|
||||
Type addJoinConstraint(ConstraintLocator *locator,
|
||||
@@ -5080,6 +5106,11 @@ public:
|
||||
LLVM_NODISCARD
|
||||
bool generateConstraints(AnyFunctionRef fn, BraceStmt *body);
|
||||
|
||||
/// Generate constraints for a given SingleValueStmtExpr.
|
||||
///
|
||||
/// \returns \c true if constraint generation failed, \c false otherwise
|
||||
bool generateConstraints(SingleValueStmtExpr *E);
|
||||
|
||||
/// Generate constraints for the given (unchecked) expression.
|
||||
///
|
||||
/// \returns a possibly-sanitized expression, or null if an error occurred.
|
||||
@@ -5978,6 +6009,22 @@ public:
|
||||
SolutionApplicationTarget)>
|
||||
rewriteTarget);
|
||||
|
||||
/// Apply the given solution to the given SingleValueStmtExpr.
|
||||
///
|
||||
/// \param solution The solution to apply.
|
||||
/// \param SVE The SingleValueStmtExpr to rewrite.
|
||||
/// \param DC The declaration context in which transformations will be
|
||||
/// applied.
|
||||
/// \param rewriteTarget Function that performs a rewrite of any
|
||||
/// solution application target within the context.
|
||||
///
|
||||
/// \returns true if solution cannot be applied.
|
||||
bool applySolutionToSingleValueStmt(
|
||||
Solution &solution, SingleValueStmtExpr *SVE, DeclContext *DC,
|
||||
std::function<
|
||||
Optional<SolutionApplicationTarget>(SolutionApplicationTarget)>
|
||||
rewriteTarget);
|
||||
|
||||
/// Reorder the disjunctive clauses for a given expression to
|
||||
/// increase the likelihood that a favored constraint will be successfully
|
||||
/// resolved before any others.
|
||||
|
||||
Reference in New Issue
Block a user