Skip to content

Commit 9f17fc9

Browse files
committed
[Completion] Fix crash in getTypeOfMember
Make sure we only attempt to query the concrete type for `Self` for a constrained protocol extension. rdar://138774888
1 parent 51dadb0 commit 9f17fc9

File tree

3 files changed

+72
-5
lines changed

3 files changed

+72
-5
lines changed

lib/IDE/CompletionLookup.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -715,8 +715,8 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD, Type ExprType) {
715715
return T;
716716

717717
// If we are doing implicit member lookup on a protocol and we have found
718-
// a declaration in an extension, use the extension's `Self` type for the
719-
// generic substitution.
718+
// a declaration in a constrained extension, use the extension's `Self`
719+
// type for the generic substitution.
720720
// Eg in the following, the `Self` type returned by `qux` is
721721
// `MyGeneric<Int>`, not `MyProto` because of the `Self` type restriction.
722722
// ```
@@ -732,9 +732,11 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD, Type ExprType) {
732732
// ```
733733
if (MaybeNominalType->isExistentialType()) {
734734
Type SelfType;
735-
if (auto ED = dyn_cast<ExtensionDecl>(VD->getDeclContext())) {
736-
SelfType = ED->getGenericSignature()->getConcreteType(
737-
ED->getSelfInterfaceType());
735+
if (auto *ED = dyn_cast<ExtensionDecl>(VD->getDeclContext())) {
736+
if (ED->getSelfProtocolDecl() && ED->isConstrainedExtension()) {
737+
auto Sig = ED->getGenericSignature();
738+
SelfType = Sig->getConcreteType(ED->getSelfInterfaceType());
739+
}
738740
}
739741
if (SelfType) {
740742
MaybeNominalType = SelfType;

test/IDE/complete_rdar138774888.swift

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %batch-code-completion
2+
3+
// rdar://138774888 - Make sure we don't crash
4+
5+
class C1 {}
6+
extension C1 {
7+
func foo() {}
8+
}
9+
protocol P1 where Self: C1 {}
10+
11+
func bar(_ x: P1) {
12+
x.#^COMPLETE1^#
13+
// COMPLETE1: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo()
14+
}
15+
16+
class C2<T> {}
17+
extension C2 where T == String {
18+
func foo() {}
19+
}
20+
extension C2 where T == Int {
21+
func bar() {}
22+
}
23+
24+
protocol P2 where Self: C2<Int> {}
25+
26+
func bar(_ x: P2) {
27+
x.#^COMPLETE2^#
28+
// COMPLETE2: Decl[InstanceMethod]/CurrNominal: bar()[#Void#]; name=bar()
29+
}

test/IDE/complete_unresolved_members.swift

+36
Original file line numberDiff line numberDiff line change
@@ -748,3 +748,39 @@ func testNestedExprPatternCompletion(_ x: SomeEnum1) {
748748
// UNRESOLVED_NESTED4: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: North[#SomeEnum1#]; name=North
749749
// UNRESOLVED_NESTED4: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; name=hash(:)
750750
}
751+
752+
protocol P1 {}
753+
protocol P2 {}
754+
struct S1: P1, P2 {}
755+
756+
extension P1 where Self == S1 {
757+
static func foo() -> Self { fatalError() }
758+
}
759+
extension P2 where Self == S1 {
760+
static func bar() -> Self { fatalError() }
761+
}
762+
763+
func testComposition() {
764+
func foo(_ x: any P1 & P2) {}
765+
foo(.#^EXISTENTIAL_COMPOSITION^#)
766+
// EXISTENTIAL_COMPOSITION-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Convertible]: foo()[#S1#]; name=foo()
767+
// EXISTENTIAL_COMPOSITION-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Convertible]: bar()[#S1#]; name=bar()
768+
}
769+
770+
protocol P3 {
771+
associatedtype X
772+
}
773+
struct S3<T> {}
774+
extension S3: P3 {
775+
typealias X = Int
776+
}
777+
778+
extension P3 where Self == S3<X> {
779+
static func foo() -> Self {}
780+
}
781+
782+
func testGenericSelfClause() {
783+
func foo(_ x: any P3) {}
784+
foo(.#^GENERIC_SELF_CLAUSE^#)
785+
// GENERIC_SELF_CLAUSE: Decl[StaticMethod]/CurrNominal/TypeRelation[Convertible]: foo()[#S3<Int>#]; name=foo()
786+
}

0 commit comments

Comments
 (0)