Skip to content

Commit 229ddf5

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.
1 parent 87db85f commit 229ddf5

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
@@ -1114,7 +1114,7 @@ static llvm::Value *emitWitnessTableAccessorCall(
11141114

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

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)