Eagerly create init(from:) when looking up 'init' on a Decodable type (#17732)
Otherwise, the initializer won't be inherited properly onto a
subclass, resulting in the base class being allocated instead of the
subclass when using Sub.init(from:).
https://bugs.swift.org/browse/SR-8083
(cherry picked from commit 9ee996cf82e9f55b3df96beb5285abd929e9ff17)
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 0519ef2..6666b6d 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -9032,6 +9032,9 @@
//
// Returns whether the target conforms to the protocol.
auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
+ if (!protocol)
+ return false;
+
auto targetType = target->getDeclaredInterfaceType();
if (auto ref = conformsToProtocol(
targetType, protocol, target,
@@ -9069,12 +9072,11 @@
}
} else {
auto argumentNames = member.getArgumentNames();
- if (argumentNames.size() != 1)
+ if (member.isCompoundName() && argumentNames.size() != 1)
return;
- auto argumentName = argumentNames.front();
if (baseName == DeclBaseName::createConstructor() &&
- argumentName == Context.Id_from) {
+ (member.isSimpleName() || argumentNames.front() == Context.Id_from)) {
// init(from:) may be synthesized as part of derived conformance to the
// Decodable protocol.
// If the target should conform to the Decodable protocol, check the
@@ -9083,7 +9085,8 @@
(void)evaluateTargetConformanceTo(decodableProto);
} else if (!baseName.isSpecial() &&
baseName.getIdentifier() == Context.Id_encode &&
- argumentName == Context.Id_to) {
+ (member.isSimpleName() ||
+ argumentNames.front() == Context.Id_to)) {
// encode(to:) may be synthesized as part of derived conformance to the
// Encodable protocol.
// If the target should conform to the Encodable protocol, check the
diff --git a/test/decl/protocol/special/coding/class_codable_inherited.swift b/test/decl/protocol/special/coding/class_codable_inherited.swift
new file mode 100644
index 0000000..c19d32c
--- /dev/null
+++ b/test/decl/protocol/special/coding/class_codable_inherited.swift
@@ -0,0 +1,25 @@
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+
+class SR8083_Base: Codable {
+ var thing: String { return "Abstract" }
+}
+
+class SR8083_Sub: SR8083_Base {
+ override var thing: String { return "Yo" }
+}
+
+func sr8083(decoder: Decoder) throws {
+ _ = try SR8083_Sub(from: decoder)
+}
+
+// CHECK-LABEL: sil_vtable SR8083_Base {
+// CHECK-DAG: #SR8083_Base.init!initializer.1: (SR8083_Base.Type) -> () -> SR8083_Base : @$S23class_codable_inherited11SR8083_BaseCACycfc // SR8083_Base.init()
+// CHECK-DAG: #SR8083_Base.init!allocator.1: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$S23class_codable_inherited11SR8083_BaseC4fromACs7Decoder_p_tKcfC
+// CHECK-DAG: #SR8083_Base.init!initializer.1: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$S23class_codable_inherited11SR8083_BaseC4fromACs7Decoder_p_tKcfc // SR8083_Base.init(from:)
+// CHECK: {{^}$}}
+
+// CHECK-LABEL: sil_vtable SR8083_Sub {
+// CHECK-DAG: #SR8083_Base.init!initializer.1: (SR8083_Base.Type) -> () -> SR8083_Base : @$S23class_codable_inherited10SR8083_SubCACycfc [override] // SR8083_Sub.init()
+// CHECK-DAG: #SR8083_Base.init!allocator.1: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$S23class_codable_inherited10SR8083_SubC4fromACs7Decoder_p_tKcfC [override] // SR8083_Sub.__allocating_init(from:)
+// CHECK-DAG: #SR8083_Base.init!initializer.1: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$S23class_codable_inherited10SR8083_SubC4fromACs7Decoder_p_tKcfc [override] // SR8083_Sub.init(from:)
+// CHECK: {{^}$}}