Skip to content

Commit 9ea0741

Browse files
committed
Sema: Carefully tweak shadowing rules
TypeChecker::lookupMemberType() performs a lookup on the base type, and disambiguates multiple results by filtering out result decls that have canonically equal types under the base type substitution. I'd like to refactor conformance checking to call lookupQualified() directly and bypass lookupMemberType(), but this requires adding a new shadowing rule to primitive name lookup to simulate the effect of the type-based disambiguation. We already had a shadowing rule which states that concrete type members shadow protocol members of the same name, but this was bypassed for member _types_. This change generalizes this rule to apply to member types also. Hopefully this doesn't break source compatibility in practice.
1 parent b1eccb5 commit 9ea0741

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

lib/AST/NameLookup.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,19 @@ static void recordShadowedDeclsAfterTypeMatch(
312312
}
313313
}
314314

315+
// If one declaration is in a protocol or extension thereof and the
316+
// other is not, prefer the one that is not.
317+
if ((bool)firstDecl->getDeclContext()->getSelfProtocolDecl() !=
318+
(bool)secondDecl->getDeclContext()->getSelfProtocolDecl()) {
319+
if (firstDecl->getDeclContext()->getSelfProtocolDecl()) {
320+
shadowed.insert(firstDecl);
321+
break;
322+
} else {
323+
shadowed.insert(secondDecl);
324+
continue;
325+
}
326+
}
327+
315328
continue;
316329
}
317330

test/NameLookup/member_type_shadowing.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,17 @@ class B: A {
2929
_ = B.Reusable.option2 // expected-error {{type 'B.Reusable' has no member 'option2'; did you mean 'option1'?}}
3030
}
3131
}
32+
33+
protocol Q {
34+
typealias A = Int
35+
}
36+
37+
struct S : Q {
38+
typealias A = String
39+
}
40+
41+
func usesA(_: S.A) {} // should resolve to the typealias inside S
42+
43+
func callsA() {
44+
usesA("hello")
45+
}

0 commit comments

Comments
 (0)