Skip to content

Commit fb760f4

Browse files
committed
[IRGen] Require same copyability to reuse layout.
Previously, in place of the layout of an aggregate which consisted of exactly one field, the layout of that one field would be used. This is incorrect in the case that the aggregate is noncopyable but the field is not. Here, it's checked that the move-only-ness of the field matches the move-only-ness of the aggregate. rdar://123197751
1 parent f4f3712 commit fb760f4

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

lib/IRGen/GenType.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2862,6 +2862,8 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t,
28622862
IGM.getSILModule().isWholeModule()));
28632863
if (!IGM.isTypeABIAccessible(fieldTy))
28642864
return SILType();
2865+
if (fieldTy.isMoveOnly() != t.isMoveOnly())
2866+
return SILType();
28652867
return fieldTy;
28662868
}
28672869

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// RUN: %target-swift-emit-irgen \
2+
// RUN: -parse-as-library \
3+
// RUN: -enable-builtin-module \
4+
// RUN: -enable-experimental-feature NoncopyableGenerics \
5+
// RUN: -enable-experimental-feature BorrowingSwitch \
6+
// RUN: %s \
7+
// RUN: | \
8+
// RUN: %FileCheck %s --check-prefix=CHECK-IR
9+
// RUN: %target-run-simple-swift(-parse-as-library -enable-builtin-module -enable-experimental-feature NoncopyableGenerics -enable-experimental-feature BorrowingSwitch -Xfrontend -sil-verify-all) | %FileCheck %s
10+
// RUN: %target-run-simple-swift(-O -parse-as-library -enable-builtin-module -enable-experimental-feature NoncopyableGenerics -enable-experimental-feature BorrowingSwitch -Xfrontend -sil-verify-all) | %FileCheck %s
11+
12+
// CHECK-IR-NOT: @"$sBpWV"
13+
14+
// CHECK: hi end
15+
// CHECK: hi 3
16+
// CHECK: hi 2
17+
// CHECK: bye 2
18+
// CHECK: bye 3
19+
// CHECK: bye end
20+
@main struct App { static func main() {
21+
let l: List<Int> = .more(
22+
2,
23+
Box(
24+
.more(3,
25+
Box(
26+
.end
27+
)
28+
)
29+
)
30+
)
31+
l.dump(prefix: "hi")
32+
l.dump(prefix: "bye")
33+
}}
34+
35+
struct Box<Wrapped: ~Copyable & Dumpable>: ~Copyable {
36+
let ptr: MyLittlePointer<Wrapped>
37+
38+
init(_ wrapped: consuming Wrapped) {
39+
wrapped.dump(prefix: "hi")
40+
ptr = .allocate(capacity: 1)
41+
ptr.initialize(to: wrapped)
42+
}
43+
44+
deinit {
45+
ptr.move().dump(prefix: "bye")
46+
ptr.deallocate()
47+
}
48+
}
49+
50+
enum List<Element>: ~Copyable, Dumpable {
51+
case end
52+
case more(Element, Box<List<Element>>)
53+
func dump(prefix: String) {
54+
switch self {
55+
case .more(let element, _):
56+
print(prefix, element)
57+
case .end:
58+
print(prefix, "end")
59+
}
60+
}
61+
}
62+
63+
protocol Dumpable : ~Copyable {
64+
func dump(prefix: String)
65+
}
66+
67+
68+
import Builtin
69+
70+
@frozen
71+
public enum MyLittleLayout<T : ~Copyable> {
72+
@_transparent
73+
public static var size: Int {
74+
return Int(Builtin.sizeof(T.self))
75+
}
76+
@_transparent
77+
public static var stride: Int {
78+
return Int(Builtin.strideof(T.self))
79+
}
80+
}
81+
82+
struct MyLittlePointer<Pointee : ~Copyable> : Copyable {
83+
public let _rawValue: Builtin.RawPointer
84+
85+
@_transparent
86+
public init(_ _rawValue: Builtin.RawPointer) {
87+
self._rawValue = _rawValue
88+
}
89+
90+
@inlinable
91+
public static func allocate(capacity count: Int)
92+
-> MyLittlePointer<Pointee> {
93+
let size = MyLittleLayout<Pointee>.stride * count
94+
let align = (0)._builtinWordValue
95+
let rawPtr = Builtin.allocRaw(size._builtinWordValue, align)
96+
Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self)
97+
return MyLittlePointer(rawPtr)
98+
}
99+
100+
@inlinable
101+
public func deallocate() {
102+
Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue)
103+
}
104+
105+
@inlinable
106+
public func initialize(to value: consuming Pointee) {
107+
Builtin.initialize(value, self._rawValue)
108+
}
109+
@inlinable
110+
public func deinitialize(count: Int) {
111+
Builtin.destroyArray(Pointee.self, _rawValue, count._builtinWordValue)
112+
}
113+
@inlinable
114+
public func move() -> Pointee {
115+
return Builtin.take(_rawValue)
116+
}
117+
}

0 commit comments

Comments
 (0)