Skip to content

Commit 427077b

Browse files
authored
Merge pull request #74901 from Azoy/static-exclusive-requirements
[Sema] Let protocols define getter requirements for @_staticExclusiveOnly types
2 parents 3626000 + 9aceb99 commit 427077b

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
@@ -1995,6 +1995,8 @@ ERROR(attr_static_exclusive_only_let_only_param,none,
19951995
"parameter of type %0 must be declared as either 'borrowing' or 'consuming'", (Type))
19961996
ERROR(attr_static_exclusive_only_mutating,none,
19971997
"type %0 cannot have mutating function %1", (Type, ValueDecl *))
1998+
ERROR(attr_static_exclusive_no_setters,none,
1999+
"variable of type %0 must not have a setter", (Type))
19982000

19992001
// @extractConstantsFromMembers
20002002
ERROR(attr_extractConstantsFromMembers_experimental,none,

lib/Sema/TypeCheckDeclPrimary.cpp

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

25902590
TypeChecker::checkDeclAttributes(VD);
25912591

2592+
auto DC = VD->getDeclContext();
2593+
25922594
if (!checkOverrides(VD)) {
25932595
// If a property has an override attribute but does not override
25942596
// anything, complain.
25952597
auto overridden = VD->getOverriddenDecl();
25962598
if (auto *OA = VD->getAttrs().getAttribute<OverrideAttr>()) {
25972599
if (!overridden) {
2598-
auto DC = VD->getDeclContext();
25992600
auto isClassContext = DC->getSelfClassDecl() != nullptr;
26002601
auto isStructOrEnumContext = DC->getSelfEnumDecl() != nullptr ||
26012602
DC->getSelfStructDecl() != nullptr;
@@ -2650,15 +2651,26 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26502651

26512652
// @_staticExclusiveOnly types cannot be put into 'var's, only 'let'.
26522653
if (auto SD = VD->getInterfaceType()->getStructOrBoundGenericStruct()) {
2653-
if (SD->getAttrs().hasAttribute<StaticExclusiveOnlyAttr>() &&
2654-
!VD->isLet()) {
2654+
if (SD->getAttrs().hasAttribute<StaticExclusiveOnlyAttr>()) {
2655+
auto isProtocolContext = isa<ProtocolDecl>(DC);
2656+
2657+
if (isProtocolContext && !VD->supportsMutation()) {
2658+
return;
2659+
}
2660+
2661+
if (VD->isLet()) {
2662+
return;
2663+
}
2664+
2665+
auto diagMsg = isProtocolContext
2666+
? diag::attr_static_exclusive_no_setters
2667+
: diag::attr_static_exclusive_only_let_only;
2668+
26552669
Ctx.Diags.diagnoseWithNotes(
2656-
VD->diagnose(diag::attr_static_exclusive_only_let_only,
2657-
VD->getInterfaceType()),
2658-
[&]() {
2659-
SD->diagnose(diag::attr_static_exclusive_only_type_nonmutating,
2660-
SD->getDeclaredInterfaceType());
2661-
});
2670+
VD->diagnose(diagMsg, VD->getInterfaceType()), [&]() {
2671+
SD->diagnose(diag::attr_static_exclusive_only_type_nonmutating,
2672+
SD->getDeclaredInterfaceType());
2673+
});
26622674
}
26632675
}
26642676
}

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)