mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -1114,7 +1114,7 @@ static llvm::Value *emitWitnessTableAccessorCall(
|
|||||||
|
|
||||||
// Emit the source metadata if we haven't yet.
|
// Emit the source metadata if we haven't yet.
|
||||||
if (!*srcMetadataCache) {
|
if (!*srcMetadataCache) {
|
||||||
*srcMetadataCache = IGF.emitTypeMetadataRef(
|
*srcMetadataCache = IGF.emitAbstractTypeMetadataRef(
|
||||||
conformance->getType()->getCanonicalType());
|
conformance->getType()->getCanonicalType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,12 +64,14 @@ struct SyncUp<Deliverable> : Synergy {
|
|||||||
|
|
||||||
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T)
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T)
|
||||||
// CHECK: entry:
|
// CHECK: entry:
|
||||||
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s14witness_method6SyncUpVMa"([[INT]] 0, %swift.type* %T)
|
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s14witness_method6SyncUpVMa"([[INT]] 255, %swift.type* %T)
|
||||||
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
|
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
|
||||||
// CHECK: [[WTABLE:%.*]] = call i8** @swift_getWitnessTable(
|
// CHECK: [[WTABLE:%.*]] = call i8** @swift_getWitnessTable(
|
||||||
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[WTABLE]], i32 2
|
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[WTABLE]], i32 2
|
||||||
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
|
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
|
||||||
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
|
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
|
||||||
|
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 0, %swift.type* [[METADATA]])
|
||||||
|
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
|
||||||
// CHECK: [[ARG:%.*]] = bitcast %T14witness_method6SyncUpV* %1 to %swift.opaque*
|
// CHECK: [[ARG:%.*]] = bitcast %T14witness_method6SyncUpV* %1 to %swift.opaque*
|
||||||
// CHECK: call swiftcc void [[WITNESS]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture swiftself [[ARG]], %swift.type* [[METADATA]], i8** [[WTABLE]])
|
// CHECK: call swiftcc void [[WITNESS]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture swiftself [[ARG]], %swift.type* [[METADATA]], i8** [[WTABLE]])
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
|
|||||||
@@ -84,10 +84,10 @@ public func single_concrete() {
|
|||||||
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
||||||
|
|
||||||
// CHECK: cacheIsNull:
|
// CHECK: cacheIsNull:
|
||||||
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa"(i64 0)
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa"(i64 255)
|
||||||
// CHECK-NEXT: [[Single_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
// CHECK-NEXT: [[Single_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
||||||
|
|
||||||
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
||||||
// 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
|
// 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
|
||||||
|
|
||||||
@@ -219,10 +219,10 @@ public func double_concrete_concrete() {
|
|||||||
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
||||||
|
|
||||||
// CHECK: cacheIsNull:
|
// CHECK: cacheIsNull:
|
||||||
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa"(i64 0)
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s42conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa"(i64 255)
|
||||||
// CHECK-NEXT: [[Double_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
// CHECK-NEXT: [[Double_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
||||||
|
|
||||||
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
||||||
// 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
|
// 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
|
||||||
// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
|
// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ public func subclassgeneric_concrete() {
|
|||||||
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
||||||
|
|
||||||
// CHECK: cacheIsNull:
|
// CHECK: cacheIsNull:
|
||||||
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa"(i64 0)
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa"(i64 255)
|
||||||
// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
||||||
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
||||||
// 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
|
// 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
|
||||||
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
||||||
@@ -118,9 +118,9 @@ public func subclassconcrete() {
|
|||||||
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
||||||
|
|
||||||
// CHECK: cacheIsNull:
|
// CHECK: cacheIsNull:
|
||||||
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass16SubclassConcreteCMa"(i64 0)
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass16SubclassConcreteCMa"(i64 255)
|
||||||
// CHECK-NEXT: [[SubclassConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
// CHECK-NEXT: [[SubclassConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
||||||
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
||||||
// 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
|
// 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
|
||||||
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
||||||
@@ -153,9 +153,9 @@ public func subclassgenericconcrete() {
|
|||||||
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
||||||
|
|
||||||
// CHECK: cacheIsNull:
|
// CHECK: cacheIsNull:
|
||||||
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass23SubclassGenericConcreteCMa"(i64 0)
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass23SubclassGenericConcreteCMa"(i64 255)
|
||||||
// CHECK-NEXT: [[SubclassGenericConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
// CHECK-NEXT: [[SubclassGenericConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
||||||
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
||||||
// 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
|
// 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
|
||||||
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ public func concrete_concrete() {
|
|||||||
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
||||||
|
|
||||||
// CHECK: cacheIsNull:
|
// CHECK: cacheIsNull:
|
||||||
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s34conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa"(i64 0)
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s34conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa"(i64 255)
|
||||||
// CHECK-NEXT: [[Double_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
// CHECK-NEXT: [[Double_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
||||||
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
||||||
// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
||||||
// 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
|
// 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
|
||||||
// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
|
// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
|
||||||
|
|||||||
31
test/Runtime/lazy_witness_table_cycle.swift
Normal file
31
test/Runtime/lazy_witness_table_cycle.swift
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// RUN: %target-run-simple-swift
|
||||||
|
// REQUIRES: executable_test
|
||||||
|
// REQUIRES: objc_interop
|
||||||
|
|
||||||
|
// SR-5958
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Property: Equatable, Hashable, Codable {
|
||||||
|
public var value: PropertyValue<Property>
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PropertyValue<P>: Equatable, Hashable where P: Equatable & Hashable {
|
||||||
|
case invalid
|
||||||
|
case date(date: Date?)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PropertyValue: Codable where P: Codable {
|
||||||
|
public func encode(to encoder: Encoder) throws {}
|
||||||
|
public init(from decoder: Decoder) throws { self = .invalid }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension String: Error {}
|
||||||
|
|
||||||
|
let encoder = JSONEncoder()
|
||||||
|
let json = try! encoder.encode(
|
||||||
|
Property(value: .invalid)
|
||||||
|
)
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
let result = try! decoder.decode(Property.self, from: json)
|
||||||
|
print(result)
|
||||||
Reference in New Issue
Block a user