Skip to content

Commit 0ff2cd9

Browse files
committed
Sema: Force Codable conformances when validating layout of a class
This ensures that the vtable of a class conforming to Encodable or Decodable always contains encode(to:) and init(from:), respectively. They might still get added in arbitrary order, however. This will be addressed in a subsequent patch. Mostly fixes <rdar://problem/35647420> and <https://bugs.swift.org/browse/SR-6468>.
1 parent e8a1524 commit 0ff2cd9

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7991,9 +7991,6 @@ static void finalizeType(TypeChecker &TC, NominalTypeDecl *nominal) {
79917991
assert(!nominal->hasClangNode());
79927992
assert(isa<SourceFile>(nominal->getModuleScopeContext()));
79937993

7994-
if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
7995-
TC.requestSuperclassLayout(classDecl);
7996-
79977994
for (auto *D : nominal->getMembers()) {
79987995
auto VD = dyn_cast<ValueDecl>(D);
79997996
if (!VD)
@@ -8016,12 +8013,33 @@ static void finalizeType(TypeChecker &TC, NominalTypeDecl *nominal) {
80168013
}
80178014
}
80188015

8019-
// FIXME: We need to add implicit initializers and dtors when a decl is
8020-
// touched, because it affects vtable layout. If you're not defining the
8021-
// class, you shouldn't have to know what the vtable layout is.
80228016
if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
8017+
// We need to add implicit initializers and dtors because it
8018+
// affects vtable layout.
80238019
TC.addImplicitConstructors(CD);
80248020
CD->addImplicitDestructor();
8021+
8022+
// We need the superclass vtable layout as well.
8023+
TC.requestSuperclassLayout(CD);
8024+
8025+
auto useConformance = [&](ProtocolDecl *protocol) {
8026+
if (auto ref = TC.conformsToProtocol(
8027+
CD->getDeclaredInterfaceType(), protocol, CD,
8028+
ConformanceCheckFlags::SkipConditionalRequirements,
8029+
SourceLoc())) {
8030+
if (ref->getConcrete()->getDeclContext() == CD)
8031+
TC.markConformanceUsed(*ref, CD);
8032+
}
8033+
};
8034+
8035+
// If the class is Encodable or Decodable, force those
8036+
// conformances to ensure that the init(from:) and
8037+
// encode(to:) members appear in the vtable.
8038+
//
8039+
// FIXME: Generalize this to other protocols for which
8040+
// we can derive conformances.
8041+
useConformance(TC.Context.getProtocol(KnownProtocolKind::Decodable));
8042+
useConformance(TC.Context.getProtocol(KnownProtocolKind::Encodable));
80258043
}
80268044

80278045
// validateDeclForNameLookup will not trigger an immediate full

0 commit comments

Comments
 (0)