Skip to content

Commit 89761de

Browse files
committed
[CodeCompletion] Don't suggest initializers on existential types
Existential types cannot be instantiated. rdar://94369218
1 parent 9857464 commit 89761de

File tree

5 files changed

+68
-13
lines changed

5 files changed

+68
-13
lines changed

lib/IDE/CompletionLookup.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,10 @@ void CompletionLookup::addConstructorCallsForType(
15651565
if (!Sink.addInitsToTopLevel)
15661566
return;
15671567

1568+
// Existential types cannot be instantiated. e.g. 'MyProtocol()'.
1569+
if (type->isExistentialType())
1570+
return;
1571+
15681572
// 'AnyObject' is not initializable.
15691573
// FIXME: Should we do this in 'AnyObjectLookupRequest'?
15701574
if (type->isAnyObject())
@@ -2017,9 +2021,10 @@ void CompletionLookup::foundDecl(ValueDecl *D, DeclVisibilityKind Reason,
20172021

20182022
if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
20192023
addGenericTypeParamRef(GP, Reason, dynamicLookupInfo);
2020-
for (auto *protocol : GP->getConformingProtocols())
2021-
addConstructorCallsForType(protocol->getDeclaredInterfaceType(),
2022-
GP->getName(), Reason, dynamicLookupInfo);
2024+
auto type =
2025+
CurrDeclContext->mapTypeIntoContext(GP->getDeclaredInterfaceType());
2026+
addConstructorCallsForType(type, GP->getName(), Reason,
2027+
dynamicLookupInfo);
20232028
return;
20242029
}
20252030

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,15 @@ static void collectPossibleCalleesByQualifiedLookup(
365365
if (!baseInstanceTy->mayHaveMembers())
366366
return;
367367

368-
// 'AnyObject' is not initializable.
369-
if (baseInstanceTy->isAnyObject() && name == DeclNameRef::createConstructor())
370-
return;
368+
if (name == DeclNameRef::createConstructor()) {
369+
// Existential types cannot be instantiated. e.g. 'MyProtocol()'.
370+
if (baseInstanceTy->isExistentialType())
371+
return;
372+
373+
// 'AnyObject' is not initializable.
374+
if (baseInstanceTy->isAnyObject())
375+
return;
376+
}
371377

372378
// Make sure we've resolved implicit members.
373379
namelookup::installSemanticMembersIfNeeded(baseInstanceTy, name);

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,7 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
11941194
if (!isa<PatternBindingInitializer>(DC) ||
11951195
!cast<PatternBindingInitializer>(DC)->getInitializedLazyVar())
11961196
LS = LS.withOnMetatype();
1197-
DC = DC->getParent();
1197+
DC = DC->getParentForLookup();
11981198
}
11991199

12001200
// We don't look for generic parameters if we are in the context of a
@@ -1210,7 +1210,7 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
12101210

12111211
if (auto *SE = dyn_cast<SubscriptDecl>(DC)) {
12121212
ExtendedType = SE->getDeclContext()->getSelfTypeInContext();
1213-
DC = DC->getParent();
1213+
DC = DC->getParentForLookup();
12141214
if (SE->isStatic())
12151215
LS = LS.withOnMetatype();
12161216
} else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
@@ -1238,7 +1238,7 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
12381238

12391239
if (AFD->getDeclContext()->isTypeContext()) {
12401240
ExtendedType = AFD->getDeclContext()->getSelfTypeInContext();
1241-
DC = DC->getParent();
1241+
DC = DC->getParentForLookup();
12421242

12431243
if (auto *FD = dyn_cast<FuncDecl>(AFD))
12441244
if (FD->isStatic())
@@ -1288,7 +1288,7 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
12881288
MemberReason = DeclVisibilityKind::MemberOfOutsideNominal;
12891289
}
12901290

1291-
DC = DC->getParent();
1291+
DC = DC->getParentForLookup();
12921292
}
12931293

12941294
if (auto SF = dyn_cast<SourceFile>(DC)) {

test/IDE/complete_init.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,12 @@ func testTopLevel() {
8181
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: E({#x: A#})[#E#]{{; name=.+}}
8282
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: F({#x: A#})[#F#]{{; name=.+}}
8383
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: F()[#F#]{{; name=.+}}
84-
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: G({#x: A#})[#G#]{{; name=.+}}
8584
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: H({#x: A#})[#H#]{{; name=.+}}
86-
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: I({#x: A#})[#I#]{{; name=.+}}
87-
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: I({#y: A#})[#I#]{{; name=.+}}
8885
// TOP_LEVEL_0-DAG: Decl[Constructor]/CurrModule: J()[#A#]{{; name=.+}}
8986
// TOP_LEVEL_0: End completions
9087
// NEGATIVE_TOP_LEVEL_0-NOT: Decl[Constructor]/CurrModule: E()
88+
// NEGATIVE_TOP_LEVEL_0-NOT: Decl[Constructor]/CurrModule: G(
89+
// NEGATIVE_TOP_LEVEL_0-NOT: Decl[Constructor]/CurrModule: I(
9190

9291
func testQualified0() {
9392
K.#^K_QUALIFIED_0^#

test/IDE/complete_rdar94369218.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-ide-test -batch-code-completion -code-complete-inits-in-postfix-expr -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
3+
4+
protocol MyProto {
5+
init(value: String)
6+
}
7+
8+
extension MyProto where Self == MyStruct {
9+
init(arg: String) { self = Self(value: arg) }
10+
}
11+
12+
struct MyStruct: MyProto {
13+
init(value: String) {}
14+
}
15+
16+
func test1() {
17+
#^GLOBALEXPR^#
18+
// GLOBALEXPR: Begin completions
19+
// GLOBALEXPR-NOT: name=MyProto(
20+
// GLOBALEXPR-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
21+
// GLOBALEXPR-DAG: Decl[Constructor]/CurrModule: MyStruct({#value: String#})[#MyStruct#]; name=MyStruct(value:)
22+
// GLOBALEXPR-DAG: Decl[Constructor]/CurrModule: MyStruct({#arg: String#})[#MyStruct#]; name=MyStruct(arg:)
23+
// GLOBALEXPR-DAG: Decl[Protocol]/CurrModule/Flair[RareType]: MyProto[#MyProto#]; name=MyProto
24+
// GLOBALEXPR-NOT: name=MyProto(
25+
// GLOBALEXPR: End completions
26+
}
27+
28+
func test2() {
29+
_ = MyProto(#^PROTOCOL_AFTER_PAREN^#
30+
// PROTOCOL_AFTER_PAREN: Begin completions
31+
// PROTOCOL_AFTER_PAREN-NOT: name=arg:
32+
// PROTOCOL_AFTER_PAREN-NOT: name=value:
33+
// PROTOCOL_AFTER_PAREN: End completions
34+
}
35+
36+
func test3<MyGeneric: MyProto>() {
37+
class Inner {
38+
func test() {
39+
#^GENERICEXPR^#
40+
// GENERICEXPR: Decl[GenericTypeParam]/Local: MyGeneric[#MyGeneric#]; name=MyGeneric
41+
// GENERICEXPR: Decl[Constructor]/Local: MyGeneric({#value: String#})[#MyProto#]; name=MyGeneric(value:)
42+
// GENERICEXPR: Decl[Constructor]/Local: MyGeneric({#arg: String#})[#MyStruct#]; name=MyGeneric(arg:)
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)