Skip to content

Commit e013ebd

Browse files
committed
[CodeCompletion] Ensure all ExtensionDecl's extended nominal are computed
Fixes an assertion failure in ASTScope lookup rdar://problem/67102794
1 parent 9993875 commit e013ebd

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ void swift::ide::typeCheckContextAt(DeclContext *DC, SourceLoc Loc) {
4646
while (isa<AbstractClosureExpr>(DC))
4747
DC = DC->getParent();
4848

49-
// Make sure the extension has been bound, in case it is in an inactive #if
50-
// or something weird like that.
49+
// Make sure the extension has been bound.
5150
{
51+
// Even if the extension is invalid (e.g. nested in a function or another
52+
// type), we want to know the "intended nominal" of the extension so that
53+
// we can know the type of 'Self'.
5254
SmallVector<ExtensionDecl *, 1> extensions;
5355
for (auto typeCtx = DC->getInnermostTypeContext(); typeCtx != nullptr;
5456
typeCtx = typeCtx->getParent()->getInnermostTypeContext()) {
@@ -59,6 +61,20 @@ void swift::ide::typeCheckContextAt(DeclContext *DC, SourceLoc Loc) {
5961
extensions.back()->computeExtendedNominal();
6062
extensions.pop_back();
6163
}
64+
65+
// If the completion happens in the inheritance clause of the extension,
66+
// 'DC' is the parent of the extension. We need to iterate the top level
67+
// decls to find it. In theory, we don't need the extended nominal in the
68+
// inheritance clause, but ASTScope lookup requires that. We don't care
69+
// unless 'DC' is not 'SourceFile' because non-toplevel extensions are
70+
// 'canNeverBeBound()' anyway.
71+
if (auto *SF = dyn_cast<SourceFile>(DC)) {
72+
auto &SM = DC->getASTContext().SourceMgr;
73+
for (auto *decl : SF->getTopLevelDecls())
74+
if (auto *ext = dyn_cast<ExtensionDecl>(decl))
75+
if (SM.rangeContainsTokenLoc(ext->getSourceRange(), Loc))
76+
ext->computeExtendedNominal();
77+
}
6278
}
6379

6480
// Type-check this context.

test/IDE/complete_type.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,3 +765,17 @@ func testUnbound2(x: OuterStruct<Int>.Inner.#^UNBOUND_DOT_3^#) {}
765765
// UNBOUND_DOT_3: Begin completions
766766
// UNBOUND_DOT_3-DAG: Keyword/None: Type[#OuterStruct<Int>.Inner.Type#]; name=Type
767767
// UNBOUND_DOT_3: End completions
768+
769+
// rdar://problem/67102794
770+
struct HasProtoAlias {
771+
typealias ProtoAlias = FooProtocol
772+
}
773+
extension FooStruct: HasProtoAlias.#^EXTENSION_INHERITANCE_1?check=EXTENSION_INHERITANCE^# {}
774+
775+
struct ContainExtension {
776+
extension FooStruct: HasProtoAlias.#^EXTENSION_INHERITANCE_2?check=EXTENSION_INHERITANCE^# {}
777+
}
778+
// EXTENSION_INHERITANCE: Begin completions, 2 items
779+
// EXTENSION_INHERITANCE-DAG: Decl[TypeAlias]/CurrNominal: ProtoAlias[#FooProtocol#];
780+
// EXTENSION_INHERITANCE-DAG: Keyword/None: Type[#HasProtoAlias.Type#];
781+
// EXTENSION_INHERITANCE: End completions

0 commit comments

Comments
 (0)