Skip to content

Commit 24ade49

Browse files
authored
Merge pull request #70418 from ahoppen/ahoppen/inherited-protocol-crash
[CodeCompletion] Fix crash when completing inside a protocol that inherits from other protocol with extension
2 parents 4de3833 + e56708c commit 24ade49

File tree

3 files changed

+30
-29
lines changed

3 files changed

+30
-29
lines changed

lib/IDE/CompletionOverrideLookup.cpp

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,35 +30,7 @@ bool CompletionOverrideLookup::addAccessControl(
3030
if (AccessOfContext < AccessLevel::Public)
3131
return false;
3232

33-
auto Access = VD->getFormalAccess();
34-
// Use the greater access between the protocol requirement and the witness.
35-
// In case of:
36-
//
37-
// public protocol P { func foo() }
38-
// public class B { func foo() {} }
39-
// public class C: B, P {
40-
// <complete>
41-
// }
42-
//
43-
// 'VD' is 'B.foo()' which is implicitly 'internal'. But as the overriding
44-
// declaration, the user needs to write both 'public' and 'override':
45-
//
46-
// public class C: B {
47-
// public override func foo() {}
48-
// }
49-
if (Access < AccessLevel::Public &&
50-
!isa<ProtocolDecl>(VD->getDeclContext())) {
51-
for (auto Conformance : CurrentNominal->getAllConformances()) {
52-
Conformance->getRootConformance()->forEachValueWitness(
53-
[&](ValueDecl *req, Witness witness) {
54-
if (witness.getDecl() == VD)
55-
Access = std::max(Access,
56-
Conformance->getProtocol()->getFormalAccess());
57-
});
58-
}
59-
}
60-
61-
Access = std::min(Access, AccessOfContext);
33+
AccessLevel Access = std::min(VD->getFormalAccess(), AccessOfContext);
6234
// Only emit 'public', not needed otherwise.
6335
if (Access < AccessLevel::Public)
6436
return false;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %batch-code-completion
2+
3+
4+
// Use the greater access between the protocol requirement and the witness. In this test
5+
// case the completed declaration is 'B.foo()' which is implicitly 'internal'.
6+
// But as the overriding declaration, the user needs to write both 'public' and 'override'.
7+
public protocol P { func foo() }
8+
public class B { internal func foo() {} }
9+
public class C: B, P {
10+
#^COMPLETE^#
11+
// COMPLETE-DAG: Decl[InstanceMethod]/Super: public override func foo() {|}; name=foo()
12+
// COMPLETE-DAG: Decl[Constructor]/Super: override init() {|}; name=init()
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %batch-code-completion
2+
3+
public protocol BaseProtocol {}
4+
5+
extension BaseProtocol {
6+
var indexInParent: Int {
7+
1
8+
}
9+
}
10+
11+
public protocol InheritedProtocol: BaseProtocol {}
12+
13+
extension InheritedProtocol {
14+
#^COMPLETE^#
15+
// COMPLETE: Decl[InstanceVar]/Super: var indexInParent: Int; name=indexInParent
16+
}

0 commit comments

Comments
 (0)