Skip to content

Commit 67d0a22

Browse files
committed
[IRGen] Do not set HasLayoutString flag for non-copyable types requiring metadata instantiation
rdar://157795547 When types contain stored properties of resilient types, we instantiate their metadata at runtime. If those types are non-copyable, they won't have layout strings, so we must not set the flag.
1 parent 14eb1e4 commit 67d0a22

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5808,8 +5808,12 @@ namespace {
58085808
return false;
58095809
}
58105810

5811-
if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnessesInstantiation) &&
5812-
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation) {
5811+
auto &TI = IGM.getTypeInfo(getLoweredType());
5812+
5813+
if (IGM.Context.LangOpts.hasFeature(
5814+
Feature::LayoutStringValueWitnessesInstantiation) &&
5815+
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation &&
5816+
TI.isCopyable(ResilienceExpansion::Maximal)) {
58135817
return !!getLayoutString() || needsSingletonMetadataInitialization(IGM, Target);
58145818
}
58155819

@@ -6285,9 +6289,11 @@ namespace {
62856289
}
62866290

62876291
bool hasInstantiatedLayoutString() {
6292+
auto &TI = IGM.getTypeInfo(getLoweredType());
62886293
if (IGM.Context.LangOpts.hasFeature(
62896294
Feature::LayoutStringValueWitnessesInstantiation) &&
6290-
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation) {
6295+
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation &&
6296+
TI.isCopyable(ResilienceExpansion::Maximal)) {
62916297
return needsSingletonMetadataInitialization(IGM, Target);
62926298
}
62936299

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,13 @@ public struct NestedWrapper<T> {
341341
}
342342
}
343343

344-
struct InternalGeneric<T> {
344+
struct InternalGeneric<T: ~Copyable>: ~Copyable {
345345
let y: Int
346346
let x: T
347347
}
348348

349+
extension InternalGeneric: Copyable where T: Copyable {}
350+
349351
public enum SinglePayloadSimpleClassEnum {
350352
case empty0
351353
case empty1
@@ -711,7 +713,7 @@ public func preSpec() {
711713
}
712714

713715
@inline(never)
714-
public func testAssign<T>(_ ptr: UnsafeMutablePointer<T>, from x: T) {
716+
public func testAssign<T: ~Copyable>(_ ptr: UnsafeMutablePointer<T>, from x: consuming T) {
715717
ptr.pointee = x
716718
}
717719

@@ -721,7 +723,7 @@ public func testAssignCopy<T>(_ ptr: UnsafeMutablePointer<T>, from x: inout T) {
721723
}
722724

723725
@inline(never)
724-
public func testInit<T>(_ ptr: UnsafeMutablePointer<T>, to x: T) {
726+
public func testInit<T: ~Copyable>(_ ptr: UnsafeMutablePointer<T>, to x: consuming T) {
725727
ptr.initialize(to: x)
726728
}
727729

@@ -731,32 +733,32 @@ public func testInitTake<T>(_ ptr: UnsafeMutablePointer<T>, to x: consuming T) {
731733
}
732734

733735
@inline(never)
734-
public func testDestroy<T>(_ ptr: UnsafeMutablePointer<T>) {
736+
public func testDestroy<T: ~Copyable>(_ ptr: UnsafeMutablePointer<T>) {
735737
_ = ptr.move()
736738
}
737739

738740
@inline(never)
739-
public func allocateInternalGenericPtr<T>(of tpe: T.Type) -> UnsafeMutableRawPointer {
741+
public func allocateInternalGenericPtr<T: ~Copyable>(of tpe: T.Type) -> UnsafeMutableRawPointer {
740742
return UnsafeMutableRawPointer(
741743
UnsafeMutablePointer<InternalGeneric<T>>.allocate(capacity: 1))
742744
}
743745

744746
@inline(never)
745-
public func testGenericAssign<T>(_ ptr: __owned UnsafeMutableRawPointer, from x: T) {
747+
public func testGenericAssign<T: ~Copyable>(_ ptr: __owned UnsafeMutableRawPointer, from x: consuming T) {
746748
let ptr = ptr.assumingMemoryBound(to: InternalGeneric<T>.self)
747749
let x = InternalGeneric(y: 23, x: x)
748750
testAssign(ptr, from: x)
749751
}
750752

751753
@inline(never)
752-
public func testGenericInit<T>(_ ptr: __owned UnsafeMutableRawPointer, to x: T) {
754+
public func testGenericInit<T: ~Copyable>(_ ptr: __owned UnsafeMutableRawPointer, to x: consuming T) {
753755
let ptr = ptr.assumingMemoryBound(to: InternalGeneric<T>.self)
754756
let x = InternalGeneric(y: 23, x: x)
755757
testInit(ptr, to: x)
756758
}
757759

758760
@inline(never)
759-
public func testGenericDestroy<T>(_ ptr: __owned UnsafeMutableRawPointer, of tpe: T.Type) {
761+
public func testGenericDestroy<T: ~Copyable>(_ ptr: __owned UnsafeMutableRawPointer, of tpe: T.Type) {
760762
let ptr = ptr.assumingMemoryBound(to: InternalGeneric<T>.self)
761763
testDestroy(ptr)
762764
}

test/Interpreter/layout_string_witnesses_dynamic.swift

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types)
55
// RUN: %target-swift-frontend -target %target-future-triple -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-layout-string-value-witnesses -enable-layout-string-value-witnesses-instantiation -enable-library-evolution -enable-autolinking-runtime-compatibility-bytecode-layouts -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
66
// RUN: %target-build-swift -target %target-future-triple -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
7-
// RUN: %target-build-swift -target %target-future-triple -g -parse-stdlib -module-name layout_string_witnesses_dynamic -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
7+
// RUN: %target-build-swift -target %target-future-triple -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -parse-stdlib -module-name layout_string_witnesses_dynamic -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
88
// RUN: %target-codesign %t/main
99
// RUN: %target-run %t/main %t/%target-library-name(layout_string_witnesses_types) | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os
1010

@@ -1275,6 +1275,72 @@ func testNonCopyableGenericEnumSimpleClass() {
12751275

12761276
testNonCopyableGenericEnumSimpleClass()
12771277

1278+
public struct NonCopyableResilientWrapper: ~Copyable {
1279+
let x: SimpleResilient
1280+
let y: Int
1281+
}
1282+
1283+
func testNonCopyableResilientStruct() {
1284+
let ptr = allocateInternalGenericPtr(of: NonCopyableResilientWrapper.self)
1285+
1286+
do {
1287+
let x = TestClass()
1288+
testGenericInit(ptr, to: NonCopyableResilientWrapper(x: SimpleResilient(x: 23, y: x), y: 5))
1289+
}
1290+
1291+
do {
1292+
let y = TestClass()
1293+
// CHECK: Before deinit
1294+
print("Before deinit")
1295+
1296+
// CHECK-NEXT: TestClass deinitialized!
1297+
testGenericAssign(ptr, from: NonCopyableResilientWrapper(x: SimpleResilient(x: 23, y: y), y: 7))
1298+
}
1299+
1300+
// CHECK-NEXT: Before deinit
1301+
print("Before deinit")
1302+
1303+
// CHECK-NEXT: TestClass deinitialized!
1304+
testGenericDestroy(ptr, of: NonCopyableResilientWrapper.self)
1305+
1306+
ptr.deallocate()
1307+
}
1308+
1309+
testNonCopyableResilientStruct()
1310+
1311+
public enum NonCopyableResilientEnum: ~Copyable {
1312+
case x(SimpleResilient, Int)
1313+
case y(Int)
1314+
}
1315+
1316+
func testNonCopyableResilientEnum() {
1317+
let ptr = allocateInternalGenericPtr(of: NonCopyableResilientEnum.self)
1318+
1319+
do {
1320+
let x = TestClass()
1321+
testGenericInit(ptr, to: NonCopyableResilientEnum.x(SimpleResilient(x: 23, y: x), 5))
1322+
}
1323+
1324+
do {
1325+
let y = TestClass()
1326+
// CHECK: Before deinit
1327+
print("Before deinit")
1328+
1329+
// CHECK-NEXT: TestClass deinitialized!
1330+
testGenericAssign(ptr, from: NonCopyableResilientEnum.x(SimpleResilient(x: 23, y: y), 7))
1331+
}
1332+
1333+
// CHECK-NEXT: Before deinit
1334+
print("Before deinit")
1335+
1336+
// CHECK-NEXT: TestClass deinitialized!
1337+
testGenericDestroy(ptr, of: NonCopyableResilientEnum.self)
1338+
1339+
ptr.deallocate()
1340+
}
1341+
1342+
testNonCopyableResilientEnum()
1343+
12781344
#if os(macOS)
12791345

12801346
import Foundation

0 commit comments

Comments
 (0)