Skip to content

Commit f0f26b4

Browse files
committed
AST: Fix ProtocolDecl::getInheritedProtocols() for protocols that inherit from compositions
We allow protocols to inherit from protocol compositions defined via a typealias, eg, typealias PQ = P & Q protocol R : PQ {} Sometimes, ProtocolDecl::getInheritedProtocols() is called before the protocol's requirement signature has been computed. In this case, we walk the inheritance clause of the protocol directly. This walk was only looking at ProtocolType members of the inheritance clause, ignoring ProtocolCompositionTypes. As a result, name lookup could fail with an assertion because of not being able to "see" members inherited via the protocol composition. Fixes <rdar://problem/32595988>.
1 parent b009770 commit f0f26b4

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

lib/AST/Decl.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2905,10 +2905,13 @@ ProtocolDecl::getInheritedProtocols() const {
29052905
// Only protocols can appear in the inheritance clause
29062906
// of a protocol -- anything else should get diagnosed
29072907
// elsewhere.
2908-
if (auto *protoTy = type->getAs<ProtocolType>()) {
2909-
auto *protoDecl = protoTy->getDecl();
2910-
if (known.insert(protoDecl).second)
2911-
result.push_back(protoDecl);
2908+
if (type->isExistentialType()) {
2909+
auto layout = type->getExistentialLayout();
2910+
for (auto protoTy : layout.getProtocols()) {
2911+
auto *protoDecl = protoTy->getDecl();
2912+
if (known.insert(protoDecl).second)
2913+
result.push_back(protoDecl);
2914+
}
29122915
}
29132916
}
29142917
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
public protocol Critter {
2+
associatedtype Fur
3+
}
4+
public protocol Pet {}
5+
6+
public typealias Cat = Critter & Pet
7+
8+
public protocol Kitten : Cat {}
9+
10+
extension Kitten {
11+
public func pet() -> Fur {
12+
while true {}
13+
}
14+
}
15+
16+
public final class Meow<Purrs> : Kitten {
17+
public typealias Fur = Purrs
18+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %target-swift-frontend -typecheck -primary-file %s %S/Inputs/protocol-inheritance.swift
2+
3+
func kitty<Purrs>(cat: Meow<Purrs>) {
4+
cat.pet()
5+
}

0 commit comments

Comments
 (0)