Skip to content

Commit 9ee996c

Browse files
authored
Eagerly create init(from:) when looking up 'init' on a Decodable type (#17712)
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
1 parent 829b10c commit 9ee996c

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6383,6 +6383,9 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
63836383
//
63846384
// Returns whether the target conforms to the protocol.
63856385
auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
6386+
if (!protocol)
6387+
return false;
6388+
63866389
auto targetType = target->getDeclaredInterfaceType();
63876390
if (auto ref = conformsToProtocol(
63886391
targetType, protocol, target,
@@ -6420,12 +6423,11 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
64206423
}
64216424
} else {
64226425
auto argumentNames = member.getArgumentNames();
6423-
if (argumentNames.size() != 1)
6426+
if (member.isCompoundName() && argumentNames.size() != 1)
64246427
return;
64256428

6426-
auto argumentName = argumentNames.front();
64276429
if (baseName == DeclBaseName::createConstructor() &&
6428-
argumentName == Context.Id_from) {
6430+
(member.isSimpleName() || argumentNames.front() == Context.Id_from)) {
64296431
// init(from:) may be synthesized as part of derived conformance to the
64306432
// Decodable protocol.
64316433
// If the target should conform to the Decodable protocol, check the
@@ -6434,7 +6436,8 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
64346436
(void)evaluateTargetConformanceTo(decodableProto);
64356437
} else if (!baseName.isSpecial() &&
64366438
baseName.getIdentifier() == Context.Id_encode &&
6437-
argumentName == Context.Id_to) {
6439+
(member.isSimpleName() ||
6440+
argumentNames.front() == Context.Id_to)) {
64386441
// encode(to:) may be synthesized as part of derived conformance to the
64396442
// Encodable protocol.
64406443
// If the target should conform to the Encodable protocol, check the
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
2+
3+
class SR8083_Base: Codable {
4+
var thing: String { return "Abstract" }
5+
}
6+
7+
class SR8083_Sub: SR8083_Base {
8+
override var thing: String { return "Yo" }
9+
}
10+
11+
func sr8083(decoder: Decoder) throws {
12+
_ = try SR8083_Sub(from: decoder)
13+
}
14+
15+
// CHECK-LABEL: sil_vtable SR8083_Base {
16+
// CHECK-DAG: #SR8083_Base.init!initializer.1: (SR8083_Base.Type) -> () -> SR8083_Base : @$S23class_codable_inherited11SR8083_BaseCACycfc // SR8083_Base.init()
17+
// CHECK-DAG: #SR8083_Base.init!allocator.1: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$S23class_codable_inherited11SR8083_BaseC4fromACs7Decoder_p_tKcfC
18+
// CHECK-DAG: #SR8083_Base.init!initializer.1: (SR8083_Base.Type) -> (Decoder) throws -> SR8083_Base : @$S23class_codable_inherited11SR8083_BaseC4fromACs7Decoder_p_tKcfc // SR8083_Base.init(from:)
19+
// CHECK: {{^}$}}
20+
21+
// CHECK-LABEL: sil_vtable SR8083_Sub {
22+
// CHECK-DAG: #SR8083_Base.init!initializer.1: (SR8083_Base.Type) -> () -> SR8083_Base : @$S23class_codable_inherited10SR8083_SubCACycfc [override] // SR8083_Sub.init()
23+
// 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:)
24+
// 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:)
25+
// CHECK: {{^}$}}

0 commit comments

Comments
 (0)