Skip to content

Commit 42683c1

Browse files
author
Harlan Haskins
authored
Merge pull request #25614 from harlanhaskins/i-saw-lookup-ignoring-super-clause-5.1
[Sema] Compute superclass of deserialized protocols via generic signature
2 parents a52081f + e46d71f commit 42683c1

File tree

7 files changed

+61
-16
lines changed

7 files changed

+61
-16
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 493; // backing variables
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 495; // remove superclass from ProtocolLayout
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -997,7 +997,6 @@ namespace decls_block {
997997
BCFixed<1>, // objc?
998998
BCFixed<1>, // existential-type-supported?
999999
GenericEnvironmentIDField, // generic environment
1000-
TypeIDField, // superclass
10011000
AccessLevelField, // access level
10021001
BCArray<DeclIDField> // inherited types
10031002
// Trailed by the generic parameters (if any), the members record, and

lib/AST/NameLookup.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/ClangModuleLoader.h"
2222
#include "swift/AST/DebuggerClient.h"
2323
#include "swift/AST/ExistentialLayout.h"
24+
#include "swift/AST/GenericSignature.h"
2425
#include "swift/AST/LazyResolver.h"
2526
#include "swift/AST/Initializer.h"
2627
#include "swift/AST/NameLookupRequests.h"
@@ -2039,6 +2040,25 @@ SuperclassDeclRequest::evaluate(Evaluator &evaluator,
20392040
NominalTypeDecl *subject) const {
20402041
auto &Ctx = subject->getASTContext();
20412042

2043+
// Protocols may get their superclass bound from a `where Self : Superclass`
2044+
// clause.
2045+
if (auto *proto = dyn_cast<ProtocolDecl>(subject)) {
2046+
// If the protocol came from a serialized module, compute the superclass via
2047+
// its generic signature.
2048+
if (proto->wasDeserialized()) {
2049+
auto superTy = proto->getGenericSignature()
2050+
->getSuperclassBound(proto->getSelfInterfaceType());
2051+
if (superTy)
2052+
return superTy->getClassOrBoundGenericClass();
2053+
}
2054+
2055+
// Otherwise check the where clause.
2056+
auto selfBounds = getSelfBoundsFromWhereClause(proto);
2057+
for (auto inheritedNominal : selfBounds.decls)
2058+
if (auto classDecl = dyn_cast<ClassDecl>(inheritedNominal))
2059+
return classDecl;
2060+
}
2061+
20422062
for (unsigned i : indices(subject->getInherited())) {
20432063
// Find the inherited declarations referenced at this position.
20442064
auto inheritedTypes = evaluateOrDefault(evaluator,
@@ -2058,15 +2078,6 @@ SuperclassDeclRequest::evaluate(Evaluator &evaluator,
20582078
}
20592079
}
20602080

2061-
// Protocols also support '... where Self : Superclass'.
2062-
auto *proto = dyn_cast<ProtocolDecl>(subject);
2063-
if (proto == nullptr)
2064-
return nullptr;
2065-
2066-
auto selfBounds = getSelfBoundsFromWhereClause(proto);
2067-
for (auto inheritedNominal : selfBounds.decls)
2068-
if (auto classDecl = dyn_cast<ClassDecl>(inheritedNominal))
2069-
return classDecl;
20702081

20712082
return nullptr;
20722083
}

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/TypeCheckRequests.h"
1717
#include "swift/AST/Decl.h"
1818
#include "swift/AST/ExistentialLayout.h"
19+
#include "swift/AST/GenericSignature.h"
1920
#include "swift/AST/NameLookupRequests.h"
2021
#include "swift/AST/TypeLoc.h"
2122
#include "swift/AST/Types.h"
@@ -84,6 +85,15 @@ SuperclassTypeRequest::evaluate(Evaluator &evaluator,
8485
TypeResolutionStage stage) const {
8586
assert(isa<ClassDecl>(nominalDecl) || isa<ProtocolDecl>(nominalDecl));
8687

88+
// If this is a protocol that came from a serialized module, compute the
89+
// superclass via its generic signature.
90+
if (auto *proto = dyn_cast<ProtocolDecl>(nominalDecl)) {
91+
if (proto->wasDeserialized()) {
92+
return proto->getGenericSignature()
93+
->getSuperclassBound(proto->getSelfInterfaceType());
94+
}
95+
}
96+
8797
for (unsigned int idx : indices(nominalDecl->getInherited())) {
8898
auto result = evaluator(InheritedTypeRequest{nominalDecl, idx, stage});
8999

lib/Serialization/Deserialization.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3291,15 +3291,13 @@ class swift::DeclDeserializer {
32913291
DeclContextID contextID;
32923292
bool isImplicit, isClassBounded, isObjC, existentialTypeSupported;
32933293
GenericEnvironmentID genericEnvID;
3294-
TypeID superclassID;
32953294
uint8_t rawAccessLevel;
32963295
ArrayRef<uint64_t> rawInheritedIDs;
32973296

32983297
decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
32993298
isImplicit, isClassBounded, isObjC,
33003299
existentialTypeSupported,
3301-
genericEnvID, superclassID,
3302-
rawAccessLevel, rawInheritedIDs);
3300+
genericEnvID, rawAccessLevel, rawInheritedIDs);
33033301

33043302
auto DC = MF.getDeclContext(contextID);
33053303
if (declOrOffset.isComplete())
@@ -3310,7 +3308,6 @@ class swift::DeclDeserializer {
33103308
/*TrailingWhere=*/nullptr);
33113309
declOrOffset = proto;
33123310

3313-
proto->setSuperclass(MF.getType(superclassID));
33143311
proto->setRequiresClass(isClassBounded);
33153312
proto->setExistentialTypeSupported(existentialTypeSupported);
33163313

lib/Serialization/Serialization.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3334,7 +3334,6 @@ void Serializer::writeDecl(const Decl *D) {
33343334
/*resolver=*/nullptr),
33353335
addGenericEnvironmentRef(
33363336
proto->getGenericEnvironment()),
3337-
addTypeRef(proto->getSuperclass()),
33383337
rawAccessLevel,
33393338
inherited);
33403339

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
public protocol P: C {}
2+
3+
public class C: P {
4+
public init() {}
5+
public func funcInClass() {}
6+
}
7+
8+
public protocol GenericP: GenericC<Int> {}
9+
10+
public class GenericC<T> {
11+
public init() {}
12+
public func funcInClass() {}
13+
}
14+
15+
extension GenericC: GenericP where T == Int {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -emit-module-path %t/ClassBoundProtocol.swiftmodule %S/Inputs/class-bound-protocol.swift -module-name ClassBoundProtocol
4+
// RUN: %target-swift-frontend -typecheck %s -I %t
5+
6+
import ClassBoundProtocol
7+
8+
func f() {
9+
let p: P = C()
10+
p.funcInClass()
11+
12+
let genericP: GenericP = GenericC<Int>()
13+
genericP.funcInClass()
14+
}

0 commit comments

Comments
 (0)