Skip to content

Commit 79a2e45

Browse files
authored
[Diag] QoI: Suggest 'weak' fix-it if unowned/unmanaged is optional (#16094)
1 parent 5030d38 commit 79a2e45

File tree

3 files changed

+26
-11
lines changed

3 files changed

+26
-11
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,6 +3243,8 @@ ERROR(invalid_ownership_protocol_type,none,
32433243
"%0 must not be applied to non-class-bound %1; "
32443244
"consider adding a protocol conformance that has a class bound",
32453245
(ReferenceOwnership, Type))
3246+
ERROR(invalid_ownership_with_optional,none,
3247+
"%0 variable cannot have optional type", (ReferenceOwnership))
32463248
ERROR(invalid_weak_ownership_not_optional,none,
32473249
"'weak' variable should have optional type %0", (Type))
32483250
ERROR(invalid_weak_let,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,32 +2146,45 @@ void TypeChecker::checkReferenceOwnershipAttr(VarDecl *var,
21462146
auto ownershipKind = attr->get();
21472147

21482148
// A weak variable must have type R? or R! for some ownership-capable type R.
2149-
Type underlyingType = type;
2149+
auto underlyingType = type->getOptionalObjectType();
2150+
auto isOptional = bool(underlyingType);
2151+
auto allowOptional = false;
21502152
switch (ownershipKind) {
21512153
case ReferenceOwnership::Strong:
21522154
llvm_unreachable("Cannot specify 'strong' in an ownership attribute");
21532155
case ReferenceOwnership::Unowned:
21542156
case ReferenceOwnership::Unmanaged:
21552157
break;
21562158
case ReferenceOwnership::Weak:
2159+
allowOptional = true;
21572160
if (var->isLet()) {
21582161
diagnose(var->getStartLoc(), diag::invalid_weak_let);
21592162
attr->setInvalid();
21602163
}
21612164

2162-
if (Type objType = type->getOptionalObjectType()) {
2163-
underlyingType = objType;
2164-
} else {
2165-
// @IBOutlet must be optional, but not necessarily weak. Let it diagnose.
2166-
if (!var->getAttrs().hasAttribute<IBOutletAttr>()) {
2167-
diagnose(var->getStartLoc(), diag::invalid_weak_ownership_not_optional,
2168-
OptionalType::get(type));
2169-
}
2170-
attr->setInvalid();
2165+
if (isOptional)
2166+
break;
2167+
2168+
// @IBOutlet must be optional, but not necessarily weak. Let it diagnose.
2169+
if (!var->getAttrs().hasAttribute<IBOutletAttr>()) {
2170+
diagnose(var->getStartLoc(), diag::invalid_weak_ownership_not_optional,
2171+
OptionalType::get(type));
21712172
}
2173+
attr->setInvalid();
21722174
break;
21732175
}
21742176

2177+
2178+
if (!allowOptional && isOptional) {
2179+
diagnose(var->getStartLoc(), diag::invalid_ownership_with_optional,
2180+
ownershipKind)
2181+
.fixItReplace(attr->getRange(), "weak");
2182+
attr->setInvalid();
2183+
}
2184+
2185+
if (!underlyingType)
2186+
underlyingType = type;
2187+
21752188
if (!underlyingType->allowsOwnership()) {
21762189
auto D = diag::invalid_ownership_type;
21772190

test/decl/var/properties.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ class OwnershipBadSub : OwnershipBase {
11091109
override weak var strongVar: AnyObject? { // expected-error {{cannot override 'strong' property with 'weak' property}}
11101110
didSet {}
11111111
}
1112-
override unowned var weakVar: AnyObject? { // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'AnyObject?'}}
1112+
override unowned var weakVar: AnyObject? { // expected-error {{'unowned' variable cannot have optional type}}
11131113
didSet {}
11141114
}
11151115
override weak var unownedVar: AnyObject { // expected-error {{'weak' variable should have optional type 'AnyObject?'}}

0 commit comments

Comments
 (0)