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:
Mark Lacey
2017-12-12 12:26:10 -08:00
parent 406a025a2d
commit 8d86619fd7
2 changed files with 94 additions and 5 deletions

View File

@@ -2494,6 +2494,18 @@ namespace {
llvm_unreachable("Already type-checked");
}
Type
createTypeVariableAndDisjunctionForIUOCoercion(Type toType,
ConstraintLocator *locator) {
auto implicitUnwrapLocator = CS.getConstraintLocator(
locator, ConstraintLocator::ImplicitlyUnwrappedCoercionResult);
auto typeVar =
CS.createTypeVariable(implicitUnwrapLocator, /*options=*/0);
CS.buildDisjunctionForImplicitlyUnwrappedOptional(typeVar, toType,
implicitUnwrapLocator);
return typeVar;
}
Type visitForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) {
auto &tc = CS.getTypeChecker();
auto fromExpr = expr->getSubExpr();
@@ -2517,6 +2529,12 @@ namespace {
// The source type can be checked-cast to the destination type.
CS.addConstraint(ConstraintKind::CheckedCast, fromType, toType, locator);
// If the result type was declared IUO, add a disjunction for
// bindings for the result of the coercion.
auto *TR = expr->getCastTypeLoc().getTypeRepr();
if (TR && TR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional)
return createTypeVariableAndDisjunctionForIUOCoercion(toType, locator);
return toType;
}
@@ -2537,8 +2555,17 @@ namespace {
auto fromType = CS.getType(expr->getSubExpr());
auto locator = CS.getConstraintLocator(expr);
CS.addExplicitConversionConstraint(fromType, toType, /*allowFixes=*/true,
locator);
// Add a conversion constraint for the direct conversion between
// types.
CS.addExplicitConversionConstraint(fromType, toType,
/*allowFixes=*/true, locator);
// If the result type was declared IUO, add a disjunction for
// bindings for the result of the coercion.
auto *TR = expr->getCastTypeLoc().getTypeRepr();
if (TR && TR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional)
return createTypeVariableAndDisjunctionForIUOCoercion(toType, locator);
return toType;
}
@@ -2561,7 +2588,16 @@ namespace {
auto fromType = CS.getType(fromExpr);
auto locator = CS.getConstraintLocator(expr);
CS.addConstraint(ConstraintKind::CheckedCast, fromType, toType, locator);
// If the result type was declared IUO, add a disjunction for
// bindings for the result of the coercion.
auto *TR = expr->getCastTypeLoc().getTypeRepr();
if (TR && TR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional)
return createTypeVariableAndDisjunctionForIUOCoercion(
OptionalType::get(toType), locator);
return OptionalType::get(toType);
}