Skip to content

Commit cfffb40

Browse files
committed
AST: Perform a top-level lookup in directReferencesForUnqualifiedTypeLookup() if necessary
UnqualifiedLookupRequest takes a DeclContext and a SourceLoc. If the SourceLoc is valid, it locates the innermost ASTScope containing this location, and starts the lookup from that scope. Also, ASTScope currently walks up the scope tree to find the innermost scope that corresponds to the given DeclContext, in case the DeclContext is a parent of the 'natural' DeclContext for this source location. We want to remove this additional behavior and make ASTScope only depend on a source file and source location. This requires changing directReferencesForUnqualifiedTypeLookup() to handle the top-level lookup case explicitly. See the comment for more details.
1 parent df1b631 commit cfffb40

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

lib/AST/NameLookup.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,7 +1946,33 @@ static DirectlyReferencedTypeDecls
19461946
directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
19471947
SourceLoc loc, DeclContext *dc,
19481948
LookupOuterResults lookupOuter) {
1949+
// In a protocol or protocol extension, the 'where' clause can refer to
1950+
// associated types without 'Self' qualification:
1951+
//
1952+
// protocol MyProto where AssocType : Q { ... }
1953+
//
1954+
// extension MyProto where AssocType == Int { ... }
1955+
//
1956+
// For this reason, ASTScope maps source locations inside the 'where'
1957+
// clause to a scope that performs the lookup into the protocol or
1958+
// protocol extension.
1959+
//
1960+
// However, protocol and protocol extensions can also put bounds on 'Self',
1961+
// for example:
1962+
//
1963+
// protocol MyProto where Self : MyClass { ... }
1964+
//
1965+
// We must start searching for 'MyClass' at the top level, otherwise
1966+
// we end up with a cycle, because qualified lookup wants to resolve
1967+
// 'Self' bounds to build the set of declarations to search inside of.
1968+
//
1969+
// To make this work, we handle the top-level lookup case explicitly
1970+
// here, bypassing unqualified lookup and ASTScope altogether.
1971+
if (dc->isModuleScopeContext())
1972+
loc = SourceLoc();
1973+
19491974
DirectlyReferencedTypeDecls results;
1975+
19501976
UnqualifiedLookupOptions options =
19511977
UnqualifiedLookupFlags::TypeLookup |
19521978
UnqualifiedLookupFlags::AllowProtocolMembers;
@@ -1958,8 +1984,8 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
19581984
auto lookup = evaluateOrDefault(ctx.evaluator,
19591985
UnqualifiedLookupRequest{descriptor}, {});
19601986
for (const auto &result : lookup.allResults()) {
1961-
if (auto typeDecl = dyn_cast<TypeDecl>(result.getValueDecl()))
1962-
results.push_back(typeDecl);
1987+
auto typeDecl = cast<TypeDecl>(result.getValueDecl());
1988+
results.push_back(typeDecl);
19631989
}
19641990

19651991
return results;

0 commit comments

Comments
 (0)