Skip to content

Commit 3d990e9

Browse files
committed
[codable] When generated encode for a property, distinguish in between static/instance properties.
Previously, we just took the first match so: 1. We would try to emit a metatype lookup of the property but had prepared an instance lookup. 2. Could get the wrong type if the static/instance property had different types. rdar://39669212
1 parent 8ef98b8 commit 3d990e9

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

lib/Sema/DerivedConformanceCodable.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,10 +604,16 @@ static void deriveBodyEncodable_encode(AbstractFunctionDecl *encodeDecl) {
604604
// Now need to generate `try container.encode(x, forKey: .x)` for all
605605
// existing properties. Optional properties get `encodeIfPresent`.
606606
for (auto *elt : codingKeysEnum->getAllElements()) {
607-
VarDecl *varDecl;
608-
for (auto decl : targetDecl->lookupDirect(DeclName(elt->getName())))
609-
if ((varDecl = dyn_cast<VarDecl>(decl)))
610-
break;
607+
VarDecl *varDecl = nullptr;
608+
for (auto decl : targetDecl->lookupDirect(DeclName(elt->getName()))) {
609+
if (auto *vd = dyn_cast<VarDecl>(decl)) {
610+
if (!vd->isStatic()) {
611+
varDecl = vd;
612+
break;
613+
}
614+
}
615+
}
616+
assert(varDecl && "Should have found at least 1 var decl");
611617

612618
// self.x
613619
auto *selfRef = createSelfDeclRef(encodeDecl);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
2+
3+
// Make sure we have an int, not a float.
4+
//
5+
// CHECK-LABEL: sil hidden @$S33struct_codable_member_type_lookup32StaticInstanceNameDisambiguationV6encode2to{{.*}}F : $@convention(method) (@in_guaranteed Encoder, StaticInstanceNameDisambiguation) -> @error Error {
6+
// CHECK: bb0([[ENCODER:%.*]] : @trivial $*Encoder, [[INPUT:%.*]] : @trivial $StaticInstanceNameDisambiguation):
7+
// CHECK: [[INT_VALUE:%.*]] = struct_extract [[INPUT]]
8+
// CHECK: [[FUNC:%.*]] = function_ref @$Ss22KeyedEncodingContainerV6encode_6forKeyySi_xtKF : $@convention(method) <τ_0_0 where τ_0_0 : CodingKey> (Int, @in_guaranteed τ_0_0, @inout KeyedEncodingContainer<τ_0_0>) -> @error Error
9+
// CHECK: try_apply [[FUNC]]<StaticInstanceNameDisambiguation.CodingKeys>([[INT_VALUE]],
10+
// CHECK: } // end sil function '$S33struct_codable_member_type_lookup32StaticInstanceNameDisambiguationV6encode2toys7Encoder_p_tKF'
11+
struct StaticInstanceNameDisambiguation : Codable {
12+
static let version: Float = 0.42
13+
let version: Int = 42
14+
}

test/decl/protocol/special/coding/struct_codable_member_type_lookup.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,3 +654,10 @@ struct sr6886 {
654654
struct Nested : Codable {}
655655
let Nested: Nested // Don't crash with a coding key that is the same as a nested type name
656656
}
657+
658+
// Don't crash if we have a static property with the same name as an ivar that
659+
// we will encode. We check the actual codegen in a SILGen test.
660+
struct StaticInstanceNameDisambiguation : Codable {
661+
static let version: Float = 0.42
662+
let version: Int = 42
663+
}

0 commit comments

Comments
 (0)