@@ -1622,6 +1622,49 @@ static bool finishLookup(const DeclContext *dc, NLOptions options,
1622
1622
return !decls.empty ();
1623
1623
}
1624
1624
1625
+ // / Inspect the given type to determine which nominal type declarations it
1626
+ // / directly references, to facilitate name lookup into those types.
1627
+ static void extractDirectlyReferencedNominalTypes (
1628
+ Type type, SmallVectorImpl<NominalTypeDecl *> &decls) {
1629
+ if (auto nominal = type->getAnyNominal ()) {
1630
+ decls.push_back (nominal);
1631
+ return ;
1632
+ }
1633
+
1634
+ if (auto archetypeTy = type->getAs <ArchetypeType>()) {
1635
+ // Look in the protocols to which the archetype conforms (always).
1636
+ for (auto proto : archetypeTy->getConformsTo ())
1637
+ decls.push_back (proto);
1638
+
1639
+ // Look into the superclasses of this archetype.
1640
+ if (auto superclass = archetypeTy->getSuperclass ()) {
1641
+ if (auto superclassDecl = superclass->getClassOrBoundGenericClass ())
1642
+ decls.push_back (superclassDecl);
1643
+ }
1644
+
1645
+ return ;
1646
+ }
1647
+
1648
+ if (auto compositionTy = type->getAs <ProtocolCompositionType>()) {
1649
+ auto layout = compositionTy->getExistentialLayout ();
1650
+
1651
+ for (auto proto : layout.getProtocols ()) {
1652
+ auto *protoDecl = proto->getDecl ();
1653
+ decls.push_back (protoDecl);
1654
+ }
1655
+
1656
+ if (auto superclass = layout.explicitSuperclass ) {
1657
+ auto *superclassDecl = superclass->getClassOrBoundGenericClass ();
1658
+ if (superclassDecl)
1659
+ decls.push_back (superclassDecl);
1660
+ }
1661
+
1662
+ return ;
1663
+ }
1664
+
1665
+ llvm_unreachable (" Not a type containing nominal types?" );
1666
+ }
1667
+
1625
1668
bool DeclContext::lookupQualified (Type type,
1626
1669
DeclName member,
1627
1670
NLOptions options,
@@ -1638,73 +1681,88 @@ bool DeclContext::lookupQualified(Type type,
1638
1681
if (auto moduleTy = type->getAs <ModuleType>())
1639
1682
return lookupQualified (moduleTy->getModule (), member, options, decls);
1640
1683
1641
- if (!typeResolver)
1642
- typeResolver = getASTContext ().getLazyResolver ();
1684
+ // Figure out which nominal types we will look into.
1685
+ SmallVector<NominalTypeDecl *, 4 > nominalTypesToLookInto;
1686
+ extractDirectlyReferencedNominalTypes (type, nominalTypesToLookInto);
1687
+
1688
+ SmallVector<TypeDecl *, 4 > declsToLookInto (nominalTypesToLookInto.begin (),
1689
+ nominalTypesToLookInto.end ());
1690
+ return lookupQualified (declsToLookInto, member, options, decls);
1691
+ }
1692
+
1693
+ bool DeclContext::lookupQualified (ArrayRef<TypeDecl *> typeDecls,
1694
+ DeclName member,
1695
+ NLOptions options,
1696
+ SmallVectorImpl<ValueDecl *> &decls) const {
1697
+ using namespace namelookup ;
1698
+ assert (decls.empty () && " additive lookup not supported" );
1699
+
1700
+ // If we have a module, look in it.
1701
+ if (typeDecls.size () == 1 && isa<ModuleDecl>(typeDecls[0 ])) {
1702
+ return lookupQualified (cast<ModuleDecl>(typeDecls[0 ]), member, options,
1703
+ decls);
1704
+ }
1643
1705
1644
1706
// Configure lookup and dig out the tracker.
1645
1707
ReferencedNameTracker *tracker = nullptr ;
1646
1708
bool isLookupCascading;
1647
1709
configureLookup (this , options, tracker, isLookupCascading);
1648
1710
1649
- // The set of nominal type declarations we should (and have) visited .
1711
+ // Tracking for the nominal types we'll visit .
1650
1712
SmallVector<NominalTypeDecl *, 4 > stack;
1651
1713
llvm::SmallPtrSet<NominalTypeDecl *, 4 > visited;
1714
+ bool sawClassDecl = false ;
1652
1715
1653
- // Note that we don't have to visit the superclass of a protocol.
1654
- // If we started with an archetype or existential, we'll visit the
1655
- // superclass because we will have added it to the stack upfront.
1656
- //
1657
- // If we started with a concrete class conforming to a protocol
1658
- // with a superclass, we will visit the superclass from the
1659
- // concrete type.
1660
- bool checkProtocolSuperclass = false ;
1716
+ // Add the given nominal type to the stack.
1717
+ auto addNominalType = [&](NominalTypeDecl *nominal) {
1718
+ if (!visited.insert (nominal).second )
1719
+ return false ;
1720
+
1721
+ if (isa<ClassDecl>(nominal))
1722
+ sawClassDecl = true ;
1661
1723
1662
- // Handle nominal types.
1663
- bool wantProtocolMembers = (options & NL_ProtocolMembers);
1664
- if (auto nominal = type->getAnyNominal ()) {
1665
- visited.insert (nominal);
1666
1724
stack.push_back (nominal);
1725
+ return true ;
1726
+ };
1667
1727
1668
- if (isa<ProtocolDecl>(nominal))
1669
- checkProtocolSuperclass = true ;
1670
- }
1671
- // Handle archetypes
1672
- else if (auto archetypeTy = type->getAs <ArchetypeType>()) {
1673
- // Look in the protocols to which the archetype conforms (always).
1674
- for (auto proto : archetypeTy->getConformsTo ())
1675
- if (visited.insert (proto).second )
1676
- stack.push_back (proto);
1728
+ // Look through the type declarations we were given, resolving
1729
+ ASTContext &ctx = getASTContext ();
1730
+ for (auto typeDecl : typeDecls) {
1731
+ // Add nominal types directly.
1732
+ if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
1733
+ addNominalType (nominal);
1734
+ continue ;
1735
+ }
1677
1736
1678
- // Look into the superclasses of this archetype.
1679
- if ( auto superclass = archetypeTy-> getSuperclass ())
1680
- if (auto superclassDecl = superclass-> getClassOrBoundGenericClass ())
1681
- if (visited. insert (superclassDecl). second )
1682
- stack. push_back (superclassDecl);
1683
- }
1684
- // Handle protocol compositions.
1685
- else if ( auto compositionTy = type-> getAs <ProtocolCompositionType>()) {
1686
- auto layout = compositionTy-> getExistentialLayout ();
1737
+ // For typealiases, extract nominal type declarations from the underlying
1738
+ // type of the typealias.
1739
+ if (auto typealias = dyn_cast<TypeAliasDecl>(typeDecl)) {
1740
+ SmallVector<NominalTypeDecl *, 4 > nominalTypeDecls;
1741
+ if (!typealias-> getUnderlyingTypeLoc (). getType ()) {
1742
+ auto lazyResolver = ctx. getLazyResolver ();
1743
+ assert (lazyResolver && " Cannot resolve underlying type of typealias " );
1744
+ lazyResolver-> resolveDeclSignature (typealias);
1745
+ }
1687
1746
1688
- for (auto proto : layout.getProtocols ()) {
1689
- auto *protoDecl = proto->getDecl ();
1690
- if (visited.insert (protoDecl).second )
1691
- stack.push_back (protoDecl);
1747
+ extractDirectlyReferencedNominalTypes (
1748
+ typealias->getUnderlyingTypeLoc ().getType (),
1749
+ nominalTypeDecls);
1750
+ for (auto nominal : nominalTypeDecls)
1751
+ addNominalType (nominal);
1752
+ continue ;
1692
1753
}
1693
1754
1694
- if (auto superclass = layout.explicitSuperclass ) {
1695
- auto *superclassDecl = superclass->getClassOrBoundGenericClass ();
1696
- if (visited.insert (superclassDecl).second )
1697
- stack.push_back (superclassDecl);
1698
- }
1699
- } else {
1700
- llvm_unreachable (" Bad type for qualified lookup" );
1755
+ llvm_unreachable (" Cannot look into multiple modules "
1756
+ " or any type parameter" );
1701
1757
}
1702
1758
1703
1759
// Whether we only want to return complete object initializers.
1704
1760
bool onlyCompleteObjectInits = false ;
1705
1761
1706
1762
// Visit all of the nominal types we know about, discovering any others
1707
1763
// we need along the way.
1764
+ auto typeResolver = ctx.getLazyResolver ();
1765
+ bool wantProtocolMembers = (options & NL_ProtocolMembers);
1708
1766
while (!stack.empty ()) {
1709
1767
auto current = stack.back ();
1710
1768
stack.pop_back ();
@@ -1759,7 +1817,7 @@ bool DeclContext::lookupQualified(Type type,
1759
1817
if (!wantProtocolMembers && !currentIsProtocol)
1760
1818
continue ;
1761
1819
1762
- if (checkProtocolSuperclass ) {
1820
+ if (!sawClassDecl ) {
1763
1821
if (auto *protoDecl = dyn_cast<ProtocolDecl>(current)) {
1764
1822
if (auto superclassDecl = protoDecl->getSuperclassDecl ()) {
1765
1823
visited.insert (superclassDecl);
0 commit comments