Skip to content

Commit e3d434f

Browse files
committed
Serialization: Serialize ProtocolDecl::getSuperclassDecl() instead of ProtocolDecl::getSuperclass()
Protocols with a superclass bound written as `protocol P where Self: C` return null from getSuperclass(). Unqualified lookup only cares about getSuperclassDecl(), so serialize that instead. Fixes rdar://problem/124478687.
1 parent 582ec11 commit e3d434f

File tree

5 files changed

+51
-15
lines changed

5 files changed

+51
-15
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4461,14 +4461,14 @@ class DeclDeserializer {
44614461
IdentifierID nameID;
44624462
DeclContextID contextID;
44634463
bool isImplicit, isClassBounded, isObjC, hasSelfOrAssocTypeRequirements;
4464-
TypeID superclassID;
4464+
DeclID superclassDeclID;
44654465
uint8_t rawAccessLevel;
44664466
ArrayRef<uint64_t> dependencyIDs;
44674467

44684468
decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
44694469
isImplicit, isClassBounded, isObjC,
44704470
hasSelfOrAssocTypeRequirements,
4471-
superclassID,
4471+
superclassDeclID,
44724472
rawAccessLevel,
44734473
dependencyIDs);
44744474

@@ -4493,8 +4493,10 @@ class DeclDeserializer {
44934493
/*TrailingWhere=*/nullptr);
44944494
declOrOffset = proto;
44954495

4496-
proto->setSuperclass(MF.getType(superclassID));
4496+
auto *superclassDecl = dyn_cast_or_null<ClassDecl>(MF.getDecl(superclassDeclID));
44974497

4498+
ctx.evaluator.cacheOutput(SuperclassDeclRequest{proto},
4499+
std::move(superclassDecl));
44984500
ctx.evaluator.cacheOutput(ProtocolRequiresClassRequest{proto},
44994501
std::move(isClassBounded));
45004502
ctx.evaluator.cacheOutput(HasSelfOrAssociatedTypeRequirementsRequest{proto},

lib/Serialization/ModuleFormat.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 865; // removal of noncopyable generics control block
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 866; // protocol superclass fix
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -1535,7 +1535,7 @@ namespace decls_block {
15351535
BCFixed<1>, // class-bounded?
15361536
BCFixed<1>, // objc?
15371537
BCFixed<1>, // existential-type-supported?
1538-
TypeIDField, // superclass
1538+
DeclIDField, // superclass decl
15391539
AccessLevelField, // access level
15401540
BCArray<TypeIDField> // dependency types
15411541
// Trailed by the inherited protocols, the generic parameters (if any),

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4353,7 +4353,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
43534353
->requiresClass(),
43544354
proto->isObjC(),
43554355
proto->hasSelfOrAssociatedTypeRequirements(),
4356-
S.addTypeRef(proto->getSuperclass()),
4356+
S.addDeclRef(proto->getSuperclassDecl()),
43574357
rawAccessLevel,
43584358
dependencyTypeIDs);
43594359

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,39 @@
1-
public protocol P: C {}
1+
//
22

3-
public class C: P {
3+
public protocol Base {}
4+
5+
extension Base {
6+
public func funcInBaseProtocol() {}
7+
}
8+
9+
//
10+
11+
public class C: Base {
412
public init() {}
513
public func funcInClass() {}
614
}
715

8-
public protocol GenericP: GenericC<Int> {}
16+
//
17+
18+
public protocol P1: C {}
19+
20+
public protocol P2 where Self: C {}
921

10-
public class GenericC<T> {
22+
public class D: C, P1, P2 {}
23+
24+
//
25+
26+
public class GenericC<T>: Base {
1127
public init() {}
1228
public func funcInClass() {}
1329
}
1430

15-
extension GenericC: GenericP where T == Int {}
31+
//
32+
33+
public protocol GenericP1: GenericC<Int> {}
34+
35+
public protocol GenericP2 where Self: GenericC<Int> {}
36+
37+
public class GenericD<T>: GenericC<T> {}
38+
39+
extension GenericD: GenericP1, GenericP2 where T == Int {}

test/Serialization/use-class-bound-protocol.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,19 @@
66
import ClassBoundProtocol
77

88
func f() {
9-
let p: P = C()
10-
p.funcInClass()
9+
let p1: any P1 = D()
10+
p1.funcInClass()
11+
p1.funcInBaseProtocol()
1112

12-
let genericP: GenericP = GenericC<Int>()
13-
genericP.funcInClass()
13+
let p2: any P2 = D()
14+
p2.funcInClass()
15+
p2.funcInBaseProtocol()
16+
17+
let genericP1: any GenericP1 = GenericD<Int>()
18+
genericP1.funcInClass()
19+
genericP1.funcInBaseProtocol()
20+
21+
let genericP2: any GenericP2 = GenericD<Int>()
22+
genericP2.funcInClass()
23+
genericP2.funcInBaseProtocol()
1424
}

0 commit comments

Comments
 (0)