Skip to content

Commit d769221

Browse files
authored
Merge pull request #73462 from slavapestov/bitwise-copyable-lookup-conformance-irgen-6.0
[6.0] Fix incorrect BitwiseCopyable conformance lookups
2 parents b8c1b70 + 31c761f commit d769221

File tree

8 files changed

+133
-13
lines changed

8 files changed

+133
-13
lines changed

lib/IRGen/GenArchetype.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ const TypeInfo *TypeConverter::convertArchetypeType(ArchetypeType *archetype) {
414414
IGM.getSwiftModule()->getASTContext().getProtocol(
415415
KnownProtocolKind::BitwiseCopyable);
416416
// The protocol won't be present in swiftinterfaces from older SDKs.
417-
if (bitwiseCopyableProtocol && IGM.getSwiftModule()->lookupConformance(
417+
if (bitwiseCopyableProtocol && IGM.getSwiftModule()->checkConformance(
418418
archetype, bitwiseCopyableProtocol)) {
419419
return BitwiseCopyableTypeInfo::create(storageType, abiAccessible);
420420
}

lib/IRGen/GenEnum.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7296,17 +7296,19 @@ ResilientEnumImplStrategy::completeEnumTypeLayout(TypeConverter &TC,
72967296
SILType Type,
72977297
EnumDecl *theEnum,
72987298
llvm::StructType *enumTy) {
7299+
auto cp = !theEnum->canBeCopyable()
7300+
? IsNotCopyable : IsCopyable;
72997301
auto abiAccessible = IsABIAccessible_t(TC.IGM.isTypeABIAccessible(Type));
73007302
auto *bitwiseCopyableProtocol =
73017303
IGM.getSwiftModule()->getASTContext().getProtocol(
73027304
KnownProtocolKind::BitwiseCopyable);
73037305
if (bitwiseCopyableProtocol &&
7304-
IGM.getSwiftModule()->lookupConformance(
7305-
theEnum->getDeclaredInterfaceType(), bitwiseCopyableProtocol)) {
7306+
IGM.getSwiftModule()->checkConformance(Type.getASTType(),
7307+
bitwiseCopyableProtocol)) {
73067308
return BitwiseCopyableTypeInfo::create(enumTy, abiAccessible);
73077309
}
73087310
return registerEnumTypeInfo(
7309-
new ResilientEnumTypeInfo(*this, enumTy, Copyable,
7311+
new ResilientEnumTypeInfo(*this, enumTy, cp,
73107312
abiAccessible));
73117313
}
73127314

lib/IRGen/GenStruct.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,8 +1705,7 @@ const TypeInfo *TypeConverter::convertStructType(TypeBase *key, CanType type,
17051705
IGM.getSwiftModule()->getASTContext().getProtocol(
17061706
KnownProtocolKind::BitwiseCopyable);
17071707
if (bitwiseCopyableProtocol &&
1708-
IGM.getSwiftModule()->lookupConformance(D->getDeclaredInterfaceType(),
1709-
bitwiseCopyableProtocol)) {
1708+
IGM.getSwiftModule()->checkConformance(type, bitwiseCopyableProtocol)) {
17101709
return BitwiseCopyableTypeInfo::create(IGM.OpaqueTy, structAccessible);
17111710
}
17121711
return &getResilientStructTypeInfo(copyable, structAccessible);

lib/IRGen/GenTuple.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ const TypeInfo *TypeConverter::convertTupleType(TupleType *tuple) {
523523
auto *bitwiseCopyableProtocol =
524524
IGM.getSwiftModule()->getASTContext().getProtocol(
525525
KnownProtocolKind::BitwiseCopyable);
526-
if (bitwiseCopyableProtocol && IGM.getSwiftModule()->lookupConformance(
526+
if (bitwiseCopyableProtocol && IGM.getSwiftModule()->checkConformance(
527527
tuple, bitwiseCopyableProtocol)) {
528528
return BitwiseCopyableTypeInfo::create(IGM.OpaqueTy, IsABIAccessible);
529529
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
import SwiftShims
8+
9+
// CHECK-LABEL: define{{.*}} swiftcc void @func1
10+
11+
// CHECK: [[METADATA_PAIR:%.*]] = phi %swift.metadata_response
12+
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[METADATA_PAIR]], 0
13+
// CHECK: [[VWT_PTR:%.*]] = getelementptr inbounds ptr, ptr [[METADATA]], {{i32|i64}} -1
14+
// CHECK: [[VWT:%.*]] = load ptr, ptr [[VWT_PTR]]
15+
// CHECK: [[DESTROY_PTR:%.*]] = getelementptr inbounds ptr, ptr [[VWT]], i32 1
16+
// CHECK: [[DESTROY:%.*]] = load ptr, ptr [[DESTROY_PTR]]
17+
// CHECK: call void [[DESTROY]]({{.*}})
18+
// CHECK: ret void
19+
20+
sil @func1 : $@convention(thin) <each V> (@in (repeat each V)) -> () {
21+
bb0(%0 : $*(repeat each V)):
22+
destroy_addr %0 : $*(repeat each V)
23+
%ret = tuple ()
24+
return %ret : $()
25+
}
26+
27+
// CHECK-LABEL: define{{.*}} swiftcc void @func2
28+
// CHECK-NOT: call void %
29+
// CHECK: ret void
30+
31+
sil @func2 : $@convention(thin) <each V where repeat each V : BitwiseCopyable> (@in (repeat each V)) -> () {
32+
bb0(%0 : $*(repeat each V)):
33+
destroy_addr %0 : $*(repeat each V)
34+
%ret = tuple ()
35+
return %ret : $()
36+
}
37+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
public struct BitwiseStruct<T> {
2+
var t: T
3+
4+
public init(t: T) { self.t = t }
5+
}
6+
7+
extension BitwiseStruct: BitwiseCopyable where T: BitwiseCopyable {}
8+
9+
public enum BitwiseEnum<T> {
10+
case t(T)
11+
}
12+
13+
extension BitwiseEnum: BitwiseCopyable where T: BitwiseCopyable {}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-build-swift-dylib(%t/%target-library-name(bitwise_copyable_other)) -enable-library-evolution %S/Inputs/bitwise_copyable_other.swift -emit-module -emit-module-path %t/bitwise_copyable_other.swiftmodule -module-name bitwise_copyable_other
4+
// RUN: %target-codesign %t/%target-library-name(bitwise_copyable_other)
5+
6+
// RUN: %target-build-swift %s -lbitwise_copyable_other -I %t -L %t -o %t/main %target-rpath(%t)
7+
// RUN: %target-codesign %t/main
8+
9+
// RUN: %target-run %t/main %t/%target-library-name(bitwise_copyable_other)
10+
11+
// REQUIRES: executable_test
12+
13+
import StdlibUnittest
14+
import bitwise_copyable_other
15+
16+
var bitwise = TestSuite("BitwiseCopyable")
17+
18+
bitwise.test("Conditional conformance with resilient struct") {
19+
func callee(_: consuming BitwiseStruct<LifetimeTracked>) {}
20+
21+
for _ in 0..<10 {
22+
callee(BitwiseStruct(t: LifetimeTracked(0)))
23+
}
24+
}
25+
26+
bitwise.test("Conditional conformance with resilient enum") {
27+
func callee(_: consuming BitwiseEnum<LifetimeTracked>) {}
28+
29+
for _ in 0..<10 {
30+
callee(BitwiseEnum.t(LifetimeTracked(0)))
31+
}
32+
}
33+
34+
runAllTests()

test/Interpreter/variadic_generic_captures.swift

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55

66
import StdlibUnittest
77

8-
var types = TestSuite("VariadicGenericCaptures")
8+
var captures = TestSuite("VariadicGenericCaptures")
99

1010
func hasMetadataPack<each T>(_: repeat each T) -> () -> Any.Type {
1111
return { return (repeat each T).self }
1212
}
1313

14-
types.test("Metadata") {
14+
captures.test("Metadata") {
1515
expectEqual(Void.self, hasMetadataPack()())
1616
expectEqual((Int, String, Bool).self, hasMetadataPack(1, "hi", false)())
1717
}
@@ -20,7 +20,7 @@ func hasWitnessTablePack<each T: Sequence>(_: repeat each T) -> () -> Any.Type {
2020
return { return (repeat (each T).Element).self }
2121
}
2222

23-
types.test("WitnessTable") {
23+
captures.test("WitnessTable") {
2424
expectEqual(Void.self, hasWitnessTablePack()())
2525
expectEqual((Int, String, Bool).self, hasWitnessTablePack([1], ["hi"], [false])())
2626
}
@@ -29,7 +29,7 @@ func hasWitnessTablePack2<each T: Sequence>(_: repeat each T) -> () -> Any.Type
2929
return { return (repeat (each T).Element.Element).self }
3030
}
3131

32-
types.test("WitnessTable2") {
32+
captures.test("WitnessTable2") {
3333
expectEqual(Void.self, hasWitnessTablePack2()())
3434
expectEqual((Int, String, Bool).self, hasWitnessTablePack2([[1]], [["hi"]], [[false]])())
3535
}
@@ -43,7 +43,7 @@ func lifetimeTest2() -> () -> Any.Type {
4343
return hasMetadataPack(3, 1.0)
4444
}
4545

46-
types.test("Lifetime") {
46+
captures.test("Lifetime") {
4747
let fn1 = lifetimeTest1()
4848
let fn2 = lifetimeTest2()
4949
expectEqual((String, Set<Int>).self, fn1())
@@ -71,7 +71,7 @@ func testNonEscapingCapture<each T: Hashable>(_ t: repeat each T) -> [AnyHashabl
7171
}
7272
}
7373

74-
types.test("CapturedValue") {
74+
captures.test("CapturedValue") {
7575
let fn1 = testEscapingCapture(1, "hi")
7676
let fn2 = testEscapingCapture(5.0, false)
7777

@@ -82,4 +82,39 @@ types.test("CapturedValue") {
8282
expectEqual([true, 7], testNonEscapingCapture(true, 7))
8383
}
8484

85+
captures.test("Leaks") {
86+
func callee<T>(_: T) {}
87+
88+
func takesEscapingClosure(_ fn: @escaping () -> ()) {
89+
fn()
90+
fn()
91+
fn()
92+
}
93+
94+
func takesNonEscapingClosure(_ fn: () -> ()) {
95+
fn()
96+
fn()
97+
fn()
98+
}
99+
100+
func formPackCaptures<each V>(_ v: repeat each V) {
101+
takesEscapingClosure { repeat callee(each v) }
102+
takesNonEscapingClosure { repeat callee(each v) }
103+
{ repeat callee(each v) }()
104+
}
105+
106+
struct S {
107+
init<each V>(_ v: repeat each V) {
108+
takesEscapingClosure { repeat callee(each v) }
109+
takesNonEscapingClosure { repeat callee(each v) }
110+
{ repeat callee(each v) }()
111+
}
112+
}
113+
114+
for _ in 0..<10 {
115+
formPackCaptures(LifetimeTracked(0), LifetimeTracked(0), LifetimeTracked(0))
116+
callee(S(LifetimeTracked(1), LifetimeTracked(1), LifetimeTracked(1)))
117+
}
118+
}
119+
85120
runAllTests()

0 commit comments

Comments
 (0)