Skip to content

Commit d94d861

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 d1d7acf commit d94d861

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
@@ -4480,14 +4480,14 @@ class DeclDeserializer {
44804480
IdentifierID nameID;
44814481
DeclContextID contextID;
44824482
bool isImplicit, isClassBounded, isObjC, hasSelfOrAssocTypeRequirements;
4483-
TypeID superclassID;
4483+
DeclID superclassDeclID;
44844484
uint8_t rawAccessLevel;
44854485
ArrayRef<uint64_t> dependencyIDs;
44864486

44874487
decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
44884488
isImplicit, isClassBounded, isObjC,
44894489
hasSelfOrAssocTypeRequirements,
4490-
superclassID,
4490+
superclassDeclID,
44914491
rawAccessLevel,
44924492
dependencyIDs);
44934493

@@ -4512,8 +4512,10 @@ class DeclDeserializer {
45124512
/*TrailingWhere=*/nullptr);
45134513
declOrOffset = proto;
45144514

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

4517+
ctx.evaluator.cacheOutput(SuperclassDeclRequest{proto},
4518+
std::move(superclassDecl));
45174519
ctx.evaluator.cacheOutput(ProtocolRequiresClassRequest{proto},
45184520
std::move(isClassBounded));
45194521
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)