Skip to content

Commit 5dd16fd

Browse files
authored
Merge pull request #8042 from slavapestov/protocol-typealias-fix
Sema: Allow protocol typealiases to witness associated type requirements
2 parents 65d4a29 + 3ab7c72 commit 5dd16fd

File tree

4 files changed

+63
-4
lines changed

4 files changed

+63
-4
lines changed

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,15 +342,15 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
342342

343343
// If we're looking up a member of a protocol, we must take special care.
344344
if (typeDecl->getDeclContext()->getAsProtocolOrProtocolExtensionContext()) {
345+
auto memberType = typeDecl->getDeclaredInterfaceType();
346+
345347
// We don't allow lookups of an associated type or typealias of an
346348
// existential type, because we have no way to represent such types.
347349
//
348350
// This is diagnosed further on down in resolveNestedIdentTypeComponent().
349351
if (type->isExistentialType() &&
350352
(isa<TypeAliasDecl>(typeDecl) ||
351353
isa<AssociatedTypeDecl>(typeDecl))) {
352-
auto memberType = typeDecl->getDeclaredInterfaceType();
353-
354354
if (memberType->hasTypeParameter()) {
355355
// If we haven't seen this type result yet, add it to the result set.
356356
if (types.insert(memberType->getCanonicalType()).second)
@@ -366,7 +366,17 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
366366
if (auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl)) {
367367
if (!type->is<ArchetypeType>() &&
368368
!type->isTypeParameter()) {
369-
inferredAssociatedTypes.push_back(assocType);
369+
if (options.contains(NameLookupFlags::PerformConformanceCheck))
370+
inferredAssociatedTypes.push_back(assocType);
371+
continue;
372+
}
373+
}
374+
375+
if (auto aliasType = dyn_cast<TypeAliasDecl>(typeDecl)) {
376+
if (!type->is<ArchetypeType>() &&
377+
!type->isTypeParameter() &&
378+
memberType->hasTypeParameter() &&
379+
!options.contains(NameLookupFlags::PerformConformanceCheck)) {
370380
continue;
371381
}
372382
}

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3213,7 +3213,7 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup(
32133213
AssociatedTypeDecl *assocType) {
32143214
// Look for a member type with the same name as the associated type.
32153215
auto candidates = TC.lookupMemberType(DC, Adoptee, assocType->getName(),
3216-
/*options=*/None);
3216+
NameLookupFlags::ProtocolMembers);
32173217

32183218
// If there aren't any candidates, we're done.
32193219
if (!candidates) {

test/decl/typealias/protocol.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,28 @@ struct OneIntSeq: MySeq, MyIterator {
9393
}
9494
}
9595

96+
protocol MyIntIterator {
97+
typealias Elem = Int
98+
}
99+
100+
struct MyIntSeq : MyIterator, MyIntIterator {
101+
func next() -> Elem? {
102+
return 0
103+
}
104+
}
105+
106+
protocol MyIntIterator2 {}
107+
108+
extension MyIntIterator2 {
109+
typealias Elem = Int
110+
}
111+
112+
struct MyIntSeq2 : MyIterator, MyIntIterator2 {
113+
func next() -> Elem? {
114+
return 0
115+
}
116+
}
117+
96118
// test for conformance correctness using typealias in extension
97119
extension MySeq {
98120
func first() -> Elem {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-frontend -typecheck -primary-file %s
2+
3+
protocol AnyCodeUnits_ {
4+
typealias IndexDistance = Int64
5+
typealias Index = Int64
6+
typealias Element = UInt32
7+
var startIndex: Index { get }
8+
var endIndex: Index { get }
9+
func index(after: Index) -> Index
10+
func index(before: Index) -> Index
11+
func index(_ i: Index, offsetBy: Int64) -> Index
12+
subscript(i: Index) -> Element { get }
13+
subscript(r: Range<Index>) -> AnyCodeUnits { get }
14+
}
15+
16+
struct AnyCodeUnits : RandomAccessCollection, AnyCodeUnits_ {
17+
let me: AnyCodeUnits_
18+
typealias Indices = DefaultRandomAccessIndices<AnyCodeUnits>
19+
var startIndex: Int64 { return me.startIndex }
20+
var endIndex: Int64 { return me.endIndex }
21+
func index(after i: Index) -> Index { return me.index(after: i) }
22+
func index(before i: Index) -> Index { return me.index(before: i) }
23+
func index(_ i: Index, offsetBy: Int64) -> Index { return me.index(i, offsetBy: i) }
24+
subscript(i: Index) -> Element { return me[i] }
25+
subscript(r: Range<Index>) -> AnyCodeUnits { return me[r] }
26+
}
27+

0 commit comments

Comments
 (0)