Skip to content

Commit f90b605

Browse files
committed
AST: Make the 'decl' name lookup behavior match type resolution more closely
Extension binding and resolution of inherited protocols uses a more primitive 'declaration' based lookup that resolves a TypeRepr directly to a set of NominalTypeDecls. This lookup differs from type resolution in a few subtle ways, namely the handling of ambiguity. In particular, if there are multiple declarations with the same name, the primitive lookup returns all of them, since it cannot perform the full ambiguity check done in type resolution, which looks at typealias underlying types. However, in the case where the multiple results are all nominal types, we can definitely fail the 'decl' name lookup right away.
1 parent 8b59660 commit f90b605

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

lib/AST/NameLookup.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,11 +2105,22 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
21052105
auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, options);
21062106
auto lookup = evaluateOrDefault(ctx.evaluator,
21072107
UnqualifiedLookupRequest{descriptor}, {});
2108+
2109+
unsigned nominalTypeDeclCount = 0;
21082110
for (const auto &result : lookup.allResults()) {
21092111
auto typeDecl = cast<TypeDecl>(result.getValueDecl());
2112+
2113+
if (isa<NominalTypeDecl>(typeDecl))
2114+
nominalTypeDeclCount++;
2115+
21102116
results.push_back(typeDecl);
21112117
}
21122118

2119+
// If we saw multiple nominal type declarations with the same name,
2120+
// the result of the lookup is definitely ambiguous.
2121+
if (nominalTypeDeclCount > 1)
2122+
results.clear();
2123+
21132124
return results;
21142125
}
21152126

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-typecheck-verify-swift -requirement-machine=verify
2+
3+
protocol Base { // expected-note {{'Base' previously declared here}}
4+
// expected-note@-1 {{found this candidate}}
5+
associatedtype E
6+
}
7+
8+
struct Base<T> {} // expected-error {{invalid redeclaration of 'Base'}}
9+
// expected-note@-1 {{found this candidate}}
10+
11+
protocol Derived : Base { // expected-error {{'Base' is ambiguous for type lookup in this context}}
12+
associatedtype E
13+
}
14+
15+
func foo<T : Derived>(_: T.E, _: T) {}

0 commit comments

Comments
 (0)