mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
IUO: Put the pieces in place to handle coercions and casts to IUO types.
For casts like 'x as T!' or 'x as! T!', generate a disjunction that attempts to bind both the optional and non-optional T, preferring the optional branch of the disjunction. Note that this should effectively be NFC at the moment because we're still generating the IUO type for T! rather than a plain optional, so we first attempt the IUO type (as opposed to an Optional<T>) which goes through existing logic that handles the IUOs as part of the type system. The new rewriting logic will actually do something once we switch over to generating Optional<T> when T! is uttered.
This commit is contained in:
@@ -3170,7 +3170,7 @@ namespace {
|
||||
cast->setImplicit();
|
||||
|
||||
// Type-check this conditional case.
|
||||
Expr *result = visitConditionalCheckedCastExpr(cast, true);
|
||||
Expr *result = handleConditionalCheckedCastExpr(cast, true);
|
||||
if (!result)
|
||||
return nullptr;
|
||||
|
||||
@@ -3409,7 +3409,28 @@ namespace {
|
||||
return addFinalOptionalInjections(result);
|
||||
}
|
||||
|
||||
bool hasForcedOptionalResult(ExplicitCastExpr *expr) {
|
||||
auto *TR = expr->getCastTypeLoc().getTypeRepr();
|
||||
if (TR && TR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) {
|
||||
auto *locator = cs.getConstraintLocator(
|
||||
expr, ConstraintLocator::ImplicitlyUnwrappedCoercionResult);
|
||||
return solution.getDisjunctionChoice(locator);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Expr *visitCoerceExpr(CoerceExpr *expr) {
|
||||
// If we need to insert a force-unwrap for coercions of the form
|
||||
// 'as T!', do so now.
|
||||
if (hasForcedOptionalResult(expr)) {
|
||||
auto *coerced = visitCoerceExpr(expr, None);
|
||||
if (!coerced)
|
||||
return nullptr;
|
||||
|
||||
return coerceImplicitlyUnwrappedOptionalToValue(
|
||||
coerced, cs.getType(coerced)->getOptionalObjectType());
|
||||
}
|
||||
|
||||
return visitCoerceExpr(expr, None);
|
||||
}
|
||||
|
||||
@@ -3482,7 +3503,24 @@ namespace {
|
||||
return expr;
|
||||
}
|
||||
|
||||
// Rewrite ForcedCheckedCastExpr based on what the solver computed.
|
||||
Expr *visitForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) {
|
||||
// If we need to insert a force-unwrap for coercions of the form
|
||||
// 'as! T!', do so now.
|
||||
if (hasForcedOptionalResult(expr)) {
|
||||
auto *coerced = handleForcedCheckedCastExpr(expr);
|
||||
if (!coerced)
|
||||
return nullptr;
|
||||
|
||||
return coerceImplicitlyUnwrappedOptionalToValue(
|
||||
coerced, cs.getType(coerced)->getOptionalObjectType());
|
||||
}
|
||||
|
||||
return handleForcedCheckedCastExpr(expr);
|
||||
}
|
||||
|
||||
// Most of the logic for dealing with ForcedCheckedCastExpr.
|
||||
Expr *handleForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) {
|
||||
// Simplify the type we're casting to.
|
||||
auto toType = simplifyType(expr->getCastTypeLoc().getType());
|
||||
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
|
||||
@@ -3546,8 +3584,23 @@ namespace {
|
||||
OptionalBindingsCastKind::Forced);
|
||||
}
|
||||
|
||||
Expr *visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr,
|
||||
bool isInsideIsExpr = false) {
|
||||
Expr *visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr) {
|
||||
// If we need to insert a force-unwrap for coercions of the form
|
||||
// 'as! T!', do so now.
|
||||
if (hasForcedOptionalResult(expr)) {
|
||||
auto *coerced = handleConditionalCheckedCastExpr(expr);
|
||||
if (!coerced)
|
||||
return nullptr;
|
||||
|
||||
return coerceImplicitlyUnwrappedOptionalToValue(
|
||||
coerced, cs.getType(coerced)->getOptionalObjectType());
|
||||
}
|
||||
|
||||
return handleConditionalCheckedCastExpr(expr);
|
||||
}
|
||||
|
||||
Expr *handleConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr,
|
||||
bool isInsideIsExpr = false) {
|
||||
// Simplify the type we're casting to.
|
||||
auto toType = simplifyType(expr->getCastTypeLoc().getType());
|
||||
checkForImportedUsedConformances(toType);
|
||||
|
||||
Reference in New Issue
Block a user