Skip to content

Commit 457c022

Browse files
committed
[IRGen] Metadata for the conforming type in a witness table access need not be complete.
When calling a witness table accessor, IRGen was forcing the conforming type to have complete metadata, even though only abstract metadata is required for that query. This could cause cyclic metadata dependencies when checking conditional conformances. Fixes SR-5958. (cherry picked from commit 229ddf5)
1 parent 00dbfa1 commit 457c022

6 files changed

+47
-14
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ static llvm::Value *emitWitnessTableAccessorCall(
11121112

11131113
// Emit the source metadata if we haven't yet.
11141114
if (!*srcMetadataCache) {
1115-
*srcMetadataCache = IGF.emitTypeMetadataRef(
1115+
*srcMetadataCache = IGF.emitAbstractTypeMetadataRef(
11161116
conformance->getType()->getCanonicalType());
11171117
}
11181118

test/IRGen/witness_method.sil

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,14 @@ struct SyncUp<Deliverable> : Synergy {
6464

6565
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T)
6666
// CHECK: entry:
67-
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s14witness_method6SyncUpVMa"([[INT]] 0, %swift.type* %T)
67+
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s14witness_method6SyncUpVMa"([[INT]] 255, %swift.type* %T)
6868
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
6969
// CHECK: [[WTABLE:%.*]] = call i8** @swift_getWitnessTable(
7070
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[WTABLE]], i32 2
7171
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
7272
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
73+
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 0, %swift.type* [[METADATA]])
74+
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
7375
// CHECK: [[ARG:%.*]] = bitcast %T14witness_method6SyncUpV* %1 to %swift.opaque*
7476
// CHECK: call swiftcc void [[WITNESS]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture swiftself [[ARG]], %swift.type* [[METADATA]], i8** [[WTABLE]])
7577
// CHECK: ret void

test/Inputs/conditional_conformance_basic_conformances.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@ public func single_concrete() {
8484
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
8585

8686
// CHECK: cacheIsNull:
87-
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa"(i64 0)
87+
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa"(i64 255)
8888
// CHECK-NEXT: [[Single_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
8989

90-
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
90+
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
9191
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
9292
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s42conditional_conformance_basic_conformances4IsP2VAA0F0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
9393

@@ -219,10 +219,10 @@ public func double_concrete_concrete() {
219219
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
220220

221221
// CHECK: cacheIsNull:
222-
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa"(i64 0)
222+
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa"(i64 255)
223223
// CHECK-NEXT: [[Double_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
224224

225-
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
225+
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
226226
// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
227227
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s42conditional_conformance_basic_conformances4IsP2VAA0F0AAWP", i32 0, i32 0), i8*** [[B_P2_PTR]], align 8
228228
// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1

test/Inputs/conditional_conformance_subclass.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ public func subclassgeneric_concrete() {
8383
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
8484

8585
// CHECK: cacheIsNull:
86-
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa"(i64 0)
86+
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa"(i64 255)
8787
// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
88-
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
88+
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
8989
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
9090
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s32conditional_conformance_subclass4IsP2VAA0E0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
9191
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
@@ -118,9 +118,9 @@ public func subclassconcrete() {
118118
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
119119

120120
// CHECK: cacheIsNull:
121-
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass16SubclassConcreteCMa"(i64 0)
121+
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass16SubclassConcreteCMa"(i64 255)
122122
// CHECK-NEXT: [[SubclassConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
123-
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
123+
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
124124
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
125125
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s32conditional_conformance_subclass4IsP2VAA0E0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
126126
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
@@ -153,9 +153,9 @@ public func subclassgenericconcrete() {
153153
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
154154

155155
// CHECK: cacheIsNull:
156-
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass23SubclassGenericConcreteCMa"(i64 0)
156+
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass23SubclassGenericConcreteCMa"(i64 255)
157157
// CHECK-NEXT: [[SubclassGenericConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
158-
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
158+
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
159159
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
160160
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s32conditional_conformance_subclass4IsP2VAA0E0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
161161
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable

test/Inputs/conditional_conformance_with_assoc.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,9 @@ public func concrete_concrete() {
200200
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
201201

202202
// CHECK: cacheIsNull:
203-
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s34conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa"(i64 0)
203+
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s34conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa"(i64 255)
204204
// CHECK-NEXT: [[Double_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
205-
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
205+
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
206206
// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
207207
// CHECK-NEXT: store i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"$s34conditional_conformance_with_assoc4IsP3VAA0F0AAWP", i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
208208
// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: executable_test
3+
// REQUIRES: objc_interop
4+
5+
// SR-5958
6+
import Foundation
7+
8+
public struct Property: Equatable, Hashable, Codable {
9+
public var value: PropertyValue<Property>
10+
}
11+
12+
public enum PropertyValue<P>: Equatable, Hashable where P: Equatable & Hashable {
13+
case invalid
14+
case date(date: Date?)
15+
}
16+
17+
extension PropertyValue: Codable where P: Codable {
18+
public func encode(to encoder: Encoder) throws {}
19+
public init(from decoder: Decoder) throws { self = .invalid }
20+
}
21+
22+
extension String: Error {}
23+
24+
let encoder = JSONEncoder()
25+
let json = try! encoder.encode(
26+
Property(value: .invalid)
27+
)
28+
29+
let decoder = JSONDecoder()
30+
let result = try! decoder.decode(Property.self, from: json)
31+
print(result)

0 commit comments

Comments
 (0)