From d93c78cedaeee48d83fa2c978ea6ccdc703bbab5 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Apr 2014 06:16:21 +0000 Subject: [PATCH] Ban @weak unchecked optionals . Swift SVN r16961 --- include/swift/AST/DiagnosticsSema.def | 3 ++ lib/Sema/TypeCheckAttr.cpp | 44 +++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 33f136a38f1..eb12834becf 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1028,6 +1028,9 @@ ERROR(invalid_ownership_opaque_type,attribute_parsing,none, "non-class type %1; consider adding a class bound", (unsigned, Type)) ERROR(invalid_weak_ownership_not_optional,attribute_parsing,none, "'weak' variable should have Optional type %0", (Type)) +ERROR(invalid_weak_ownership_unchecked_optional,attribute_parsing,none, + "'weak' variable cannot have unchecked optional type %0; did you mean " + "'unowned'?", (Type)) // requires_stored_property_inits ERROR(requires_stored_property_inits_nonclass,attribute_parsing,none, diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index b1e1aa4669d..c94b4325786 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -388,11 +388,12 @@ void TypeChecker::checkOwnershipAttr(VarDecl *var, Ownership ownershipKind) { if (type->is()) return; - // A @weak variable must have type R?, possibly @unchecked, for - // some ownership-capable type R. + // A @weak variable must have type R? for some ownership-capable + // type R. if (ownershipKind == Ownership::Weak) { - Type objType = type->getAnyOptionalObjectType(); - + OptionalTypeKind kind; + Type objType = type->getAnyOptionalObjectType(kind); + // Use this special diagnostic if it's actually a reference type // but just isn't Optional. if (!objType && type->allowsOwnership()) { @@ -403,6 +404,33 @@ void TypeChecker::checkOwnershipAttr(VarDecl *var, Ownership ownershipKind) { return; } else if (objType) { type = objType; + + // Cannot use an unchecked optional with @weak. + if (kind == OTK_UncheckedOptional) { + // Find the location of the '!'. + SourceLoc bangLoc; + auto *pattern = var->getParentPattern()->getPattern(); + if (auto *varPattern = dyn_cast(pattern)) { + pattern = varPattern->getSubPattern(); + } + if (auto *typedPattern = dyn_cast(pattern)) { + auto typeRepr = typedPattern->getTypeLoc().getTypeRepr(); + if (auto unchecked = dyn_cast(typeRepr)) { + bangLoc = unchecked->getExclamationLoc(); + } + } + + SourceLoc weakLoc = var->getAttrs().getLoc(AK_weak); + diagnose(var->getStartLoc(), + diag::invalid_weak_ownership_unchecked_optional, + type) + .fixItReplace(weakLoc, "unowned") + .fixItRemove(bangLoc); + var->getMutableAttrs().clearOwnership(); + + // FIXME: Fix the AST here. + return; + } } } @@ -444,7 +472,10 @@ void TypeChecker::checkIBOutlet(VarDecl *VD) { if (auto refStorageType = type->getAs()) { ownership = refStorageType->getOwnership(); type = refStorageType->getReferentType(); + } else if (VD->getAttrs().hasOwnership()) { + ownership = Ownership::Weak; } + if (auto optObjectType = type->getAnyOptionalObjectType()) { isOptional = true; type = optObjectType; @@ -473,9 +504,10 @@ void TypeChecker::checkIBOutlet(VarDecl *VD) { // If the type wasn't optional before, turn it into an @unchecked optional // now. if (!isOptional) { - type = UncheckedOptionalType::get(type); - if (ownership != Ownership::Strong) + if (ownership == Ownership::Weak) type = ReferenceStorageType::get(type, ownership, Context); + else + type = UncheckedOptionalType::get(type); VD->overwriteType(type); } }