Skip to content

Commit 137ef22

Browse files
committed
[CodeCompletion] Optimize member lookup in protocols being conformed to
1 parent ca686a5 commit 137ef22

File tree

1 file changed

+41
-23
lines changed

1 file changed

+41
-23
lines changed

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,9 @@ static void lookupDeclsFromProtocolsBeingConformedTo(
415415
}
416416

417417
DeclVisibilityKind ReasonForThisProtocol;
418-
if (Reason == DeclVisibilityKind::MemberOfCurrentNominal)
418+
if (Conformance->getKind() == ProtocolConformanceKind::Inherited)
419+
ReasonForThisProtocol = getReasonForSuper(Reason);
420+
else if (Reason == DeclVisibilityKind::MemberOfCurrentNominal)
419421
ReasonForThisProtocol =
420422
DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal;
421423
else
@@ -629,50 +631,66 @@ static void lookupVisibleMemberDeclsImpl(
629631
}
630632
}
631633

632-
llvm::SmallPtrSet<ClassDecl *, 8> Ancestors;
633-
do {
634-
NominalTypeDecl *CurNominal = BaseTy->getAnyNominal();
635-
if (!CurNominal)
636-
break;
637-
638-
synthesizeMemberDeclsForLookup(CurNominal, CurrDC);
634+
const auto synthesizeAndLookupTypeMembers = [&](NominalTypeDecl *NTD) {
635+
synthesizeMemberDeclsForLookup(NTD, CurrDC);
639636

640637
// Look in for members of a nominal type.
641638
lookupTypeMembers(BaseTy, BaseTy, Consumer, CurrDC, LS, Reason);
639+
};
640+
641+
llvm::SmallPtrSet<ClassDecl *, 8> Ancestors;
642+
{
643+
const auto NTD = BaseTy->getAnyNominal();
644+
if (NTD == nullptr)
645+
return;
646+
647+
synthesizeAndLookupTypeMembers(NTD);
642648
lookupDeclsFromProtocolsBeingConformedTo(BaseTy, Consumer, LS, CurrDC,
643649
Reason, Visited);
644-
// If we have a class type, look into its superclass.
645-
auto *CurClass = dyn_cast<ClassDecl>(CurNominal);
646650

651+
const auto CD = dyn_cast<ClassDecl>(NTD);
647652
// FIXME: We check `getSuperclass()` here because we'll be using the
648653
// superclass Type below, and in ill-formed code `hasSuperclass()` could
649654
// be true while `getSuperclass()` returns null, because the latter
650655
// looks for a declaration.
651-
if (CurClass && CurClass->getSuperclass()) {
656+
//
657+
// If we have a superclass, switch state and look into the
658+
// inheritance chain.
659+
if (CD && CD->getSuperclass()) {
660+
Ancestors.insert(CD);
661+
662+
Reason = getReasonForSuper(Reason);
663+
BaseTy = CD->getSuperclass();
664+
665+
LS = LS.withOnSuperclass();
666+
if (CD->inheritsSuperclassInitializers())
667+
LS = LS.withInheritsSuperclassInitializers();
668+
} else {
669+
return;
670+
}
671+
}
672+
673+
// Look into the inheritance chain.
674+
while (const auto CurClass = cast_or_null<ClassDecl>(
675+
BaseTy->getAnyNominal())) {
676+
synthesizeAndLookupTypeMembers(CurClass);
677+
if (const auto superclassTy = CurClass->getSuperclass()) {
652678
// FIXME: This path is no substitute for an actual circularity check.
653679
// The real fix is to check that the superclass doesn't introduce a
654680
// circular reference before it's written into the AST.
655681
if (Ancestors.count(CurClass)) {
656682
break;
657683
}
684+
Ancestors.insert(CurClass);
658685

659-
BaseTy = CurClass->getSuperclass();
660-
Reason = getReasonForSuper(Reason);
686+
BaseTy = superclassTy;
661687

662-
bool InheritsSuperclassInitializers =
663-
CurClass->inheritsSuperclassInitializers();
664-
if (LS.isOnSuperclass() && !InheritsSuperclassInitializers)
688+
if (!CurClass->inheritsSuperclassInitializers())
665689
LS = LS.withoutInheritsSuperclassInitializers();
666-
else if (!LS.isOnSuperclass()) {
667-
LS = LS.withOnSuperclass();
668-
if (InheritsSuperclassInitializers)
669-
LS = LS.withInheritsSuperclassInitializers();
670-
}
671690
} else {
672691
break;
673692
}
674-
Ancestors.insert(CurClass);
675-
} while (1);
693+
}
676694
}
677695

678696
swift::DynamicLookupInfo::DynamicLookupInfo(

0 commit comments

Comments
 (0)