mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Ban @weak unchecked optionals <rdar://problem/16738545>.
Swift SVN r16961
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -388,11 +388,12 @@ void TypeChecker::checkOwnershipAttr(VarDecl *var, Ownership ownershipKind) {
|
||||
if (type->is<ReferenceStorageType>())
|
||||
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<VarPattern>(pattern)) {
|
||||
pattern = varPattern->getSubPattern();
|
||||
}
|
||||
if (auto *typedPattern = dyn_cast<TypedPattern>(pattern)) {
|
||||
auto typeRepr = typedPattern->getTypeLoc().getTypeRepr();
|
||||
if (auto unchecked = dyn_cast<UncheckedOptionalTypeRepr>(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<ReferenceStorageType>()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user