Skip to content

Commit 3bc381b

Browse files
Merge pull request swiftlang#34214 from AnthonyLatsis/coself-mut
Sema: Disallow usage of settable Self-returning storage requirements …
2 parents 53560fe + 8f43d88 commit 3bc381b

File tree

2 files changed

+52
-12
lines changed

2 files changed

+52
-12
lines changed

lib/AST/Decl.cpp

+16-12
Original file line numberDiff line numberDiff line change
@@ -4843,21 +4843,19 @@ ProtocolDecl::findProtocolSelfReferences(const ValueDecl *value,
48434843
return result;
48444844
}
48454845

4846-
return ::findProtocolSelfReferences(this, type,
4847-
skipAssocTypes);
4848-
} else if (auto subscript = dyn_cast<SubscriptDecl>(value)) {
4849-
// Check the requirements of a generic subscript.
4850-
if (subscript->isGeneric()) {
4851-
if (auto result =
4852-
::findProtocolSelfReferences(this,
4853-
subscript->getGenericSignature()))
4854-
return result;
4855-
}
4856-
48574846
return ::findProtocolSelfReferences(this, type,
48584847
skipAssocTypes);
48594848
} else {
4860-
assert(isa<VarDecl>(value));
4849+
assert(isa<AbstractStorageDecl>(value));
4850+
4851+
if (auto *const subscript = dyn_cast<SubscriptDecl>(value)) {
4852+
// Check the requirements of a generic subscript.
4853+
if (subscript->isGeneric()) {
4854+
if (auto result = ::findProtocolSelfReferences(
4855+
this, subscript->getGenericSignature()))
4856+
return result;
4857+
}
4858+
}
48614859

48624860
return ::findProtocolSelfReferences(this, type,
48634861
skipAssocTypes);
@@ -4875,6 +4873,12 @@ bool ProtocolDecl::isAvailableInExistential(const ValueDecl *decl) const {
48754873
if (selfKind.parameter || selfKind.other)
48764874
return false;
48774875

4876+
// FIXME: Appropriately diagnose assignments instead.
4877+
if (auto *const storageDecl = dyn_cast<AbstractStorageDecl>(decl)) {
4878+
if (selfKind.result && storageDecl->supportsMutation())
4879+
return false;
4880+
}
4881+
48784882
return true;
48794883
}
48804884

test/decl/protocol/req/dynamic_self.swift

+36
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,39 @@ enum EError : P { // expected-error{{type 'EError' does not conform to protocol
8686
subscript() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}}
8787
func f() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}}
8888
}
89+
90+
91+
// Settable storage declaration requirements with a 'Self' result type may not
92+
// be used with an existential base.
93+
protocol P2 {
94+
subscript() -> Self { get set }
95+
}
96+
protocol P3 {
97+
var prop: Self { get set }
98+
}
99+
protocol P4 {
100+
subscript<T: Sequence>() -> T where T.Element == Self { get set }
101+
}
102+
func takesP2P3P4(p2: P2, p3: P3, p4: P4) { }
103+
// expected-error@-1{{protocol 'P2' can only be used as a generic constraint because it has Self or associated type requirements}}
104+
// expected-error@-2{{protocol 'P3' can only be used as a generic constraint because it has Self or associated type requirements}}
105+
106+
protocol P5 {
107+
}
108+
extension P5 {
109+
var prop: Self {
110+
get { self }
111+
set { }
112+
}
113+
114+
subscript() -> Self {
115+
get { self }
116+
set { }
117+
}
118+
}
119+
func takesP5(p5: P5) {
120+
_ = p5[]
121+
// expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P5'; use a generic constraint instead}}
122+
_ = p5.prop
123+
// expected-error@-1{{member 'prop' cannot be used on value of protocol type 'P5'; use a generic constraint instead}}
124+
}

0 commit comments

Comments
 (0)