Skip to content

Commit 3db75bd

Browse files
authored
Merge pull request #75296 from Azoy/60-static-exclusive-requirements
[6.0] [Sema] Let protocols define getter requirements for @_staticExclusiveOnly types
2 parents 6890224 + 9eb86da commit 3db75bd

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,8 @@ ERROR(attr_static_exclusive_only_let_only_param,none,
19921992
"parameter of type %0 must be declared as either 'borrowing' or 'consuming'", (Type))
19931993
ERROR(attr_static_exclusive_only_mutating,none,
19941994
"type %0 cannot have mutating function %1", (Type, ValueDecl *))
1995+
ERROR(attr_static_exclusive_no_setters,none,
1996+
"variable of type %0 must not have a setter", (Type))
19951997

19961998
// @extractConstantsFromMembers
19971999
ERROR(attr_extractConstantsFromMembers_experimental,none,

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,13 +2585,14 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
25852585

25862586
TypeChecker::checkDeclAttributes(VD);
25872587

2588+
auto DC = VD->getDeclContext();
2589+
25882590
if (!checkOverrides(VD)) {
25892591
// If a property has an override attribute but does not override
25902592
// anything, complain.
25912593
auto overridden = VD->getOverriddenDecl();
25922594
if (auto *OA = VD->getAttrs().getAttribute<OverrideAttr>()) {
25932595
if (!overridden) {
2594-
auto DC = VD->getDeclContext();
25952596
auto isClassContext = DC->getSelfClassDecl() != nullptr;
25962597
auto isStructOrEnumContext = DC->getSelfEnumDecl() != nullptr ||
25972598
DC->getSelfStructDecl() != nullptr;
@@ -2646,15 +2647,26 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26462647

26472648
// @_staticExclusiveOnly types cannot be put into 'var's, only 'let'.
26482649
if (auto SD = VD->getInterfaceType()->getStructOrBoundGenericStruct()) {
2649-
if (SD->getAttrs().hasAttribute<StaticExclusiveOnlyAttr>() &&
2650-
!VD->isLet()) {
2650+
if (SD->getAttrs().hasAttribute<StaticExclusiveOnlyAttr>()) {
2651+
auto isProtocolContext = isa<ProtocolDecl>(DC);
2652+
2653+
if (isProtocolContext && !VD->supportsMutation()) {
2654+
return;
2655+
}
2656+
2657+
if (VD->isLet()) {
2658+
return;
2659+
}
2660+
2661+
auto diagMsg = isProtocolContext
2662+
? diag::attr_static_exclusive_no_setters
2663+
: diag::attr_static_exclusive_only_let_only;
2664+
26512665
Ctx.Diags.diagnoseWithNotes(
2652-
VD->diagnose(diag::attr_static_exclusive_only_let_only,
2653-
VD->getInterfaceType()),
2654-
[&]() {
2655-
SD->diagnose(diag::attr_static_exclusive_only_type_nonmutating,
2656-
SD->getDeclaredInterfaceType());
2657-
});
2666+
VD->diagnose(diagMsg, VD->getInterfaceType()), [&]() {
2667+
SD->diagnose(diag::attr_static_exclusive_only_type_nonmutating,
2668+
SD->getDeclaredInterfaceType());
2669+
});
26582670
}
26592671
}
26602672
}

test/attr/attr_static_exclusive_only.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ struct B: ~Copyable { // expected-note {{'B' is a non-mutable type}}
99
// expected-note@-2 {{'B' is a non-mutable type}}
1010
// expected-note@-3 {{'B' is a non-mutable type}}
1111
// expected-note@-4 {{'B' is a non-mutable type}}
12+
// expected-note@-5 {{'B' is a non-mutable type}}
13+
// expected-note@-6 {{'B' is a non-mutable type}}
14+
// expected-note@-7 {{'B' is a non-mutable type}}
1215
mutating func change() { // expected-error {{type 'B' cannot have mutating function 'change()'}}
1316
print("123")
1417
}
@@ -68,3 +71,31 @@ func p(_: (consuming B) -> ()) {} // OK
6871
struct Q<T>: ~Copyable {} // expected-note {{'Q<T>' is a non-mutable type}}
6972

7073
var r0 = Q<Int>() // expected-error {{variable of type 'Q<Int>' must be declared with a 'let'}}
74+
75+
protocol S {
76+
var t0: B { get } // OK
77+
78+
var t1: B { get set } // expected-error {{variable of type 'B' must not have a setter}}
79+
}
80+
81+
protocol U: ~Copyable {
82+
var v: B { get } // OK
83+
}
84+
85+
struct W: ~Copyable {}
86+
87+
extension W: U {
88+
var v: B { // expected-error {{variable of type 'B' must be declared with a 'let'}}
89+
B()
90+
}
91+
}
92+
93+
struct X: ~Copyable, U {
94+
let v: B // OK
95+
}
96+
97+
extension U {
98+
var y: B { // expected-error {{variable of type 'B' must be declared with a 'let'}}
99+
B()
100+
}
101+
}

0 commit comments

Comments
 (0)