AST: Simplify Optional default initialization behavior

This commit is contained in:
Slava Pestov
2019-07-15 23:24:09 -04:00
parent 96f1b95901
commit 25e4ca9a60
4 changed files with 26 additions and 28 deletions

View File

@@ -1559,7 +1559,7 @@ bool VarDecl::isInitExposedToClients() const {
/// Check whether the given type representation will be
/// default-initializable.
static bool isDefaultInitializable(const TypeRepr *typeRepr) {
static bool isDefaultInitializable(const TypeRepr *typeRepr, ASTContext &ctx) {
// Look through most attributes.
if (const auto attributed = dyn_cast<AttributedTypeRepr>(typeRepr)) {
// Ownership kinds have optionalness requirements.
@@ -1567,7 +1567,7 @@ static bool isDefaultInitializable(const TypeRepr *typeRepr) {
ReferenceOwnershipOptionality::Required)
return true;
return isDefaultInitializable(attributed->getTypeRepr());
return isDefaultInitializable(attributed->getTypeRepr(), ctx);
}
// Optional types are default-initializable.
@@ -1575,6 +1575,20 @@ static bool isDefaultInitializable(const TypeRepr *typeRepr) {
isa<ImplicitlyUnwrappedOptionalTypeRepr>(typeRepr))
return true;
// Also support the desugared 'Optional<T>' spelling.
if (!ctx.isSwiftVersionAtLeast(5)) {
if (auto *identRepr = dyn_cast<SimpleIdentTypeRepr>(typeRepr)) {
if (identRepr->getIdentifier() == ctx.Id_Void)
return true;
}
if (auto *identRepr = dyn_cast<GenericIdentTypeRepr>(typeRepr)) {
if (identRepr->getIdentifier() == ctx.Id_Optional &&
identRepr->getNumGenericArgs() == 1)
return true;
}
}
// Tuple types are default-initializable if all of their element
// types are.
if (const auto tuple = dyn_cast<TupleTypeRepr>(typeRepr)) {
@@ -1583,7 +1597,7 @@ static bool isDefaultInitializable(const TypeRepr *typeRepr) {
return false;
for (const auto elt : tuple->getElements()) {
if (!isDefaultInitializable(elt.Type))
if (!isDefaultInitializable(elt.Type, ctx))
return false;
}
@@ -1635,11 +1649,13 @@ bool PatternBindingDecl::isDefaultInitializable(unsigned i) const {
if (entry.getPattern()->isNeverDefaultInitializable())
return false;
auto &ctx = getASTContext();
// If the pattern is typed as optional (or tuples thereof), it is
// default initializable.
if (const auto typedPattern = dyn_cast<TypedPattern>(entry.getPattern())) {
if (const auto typeRepr = typedPattern->getTypeLoc().getTypeRepr()) {
if (::isDefaultInitializable(typeRepr))
if (::isDefaultInitializable(typeRepr, ctx))
return true;
} else if (typedPattern->isImplicit()) {
// Lazy vars have implicit storage assigned to back them. Because the