Skip to content

Commit 788aa54

Browse files
committed
IRGen: Don't attempt to outline value operations on existentials that contain local archetypes
Fixes rdar://problem/118437883.
1 parent b073165 commit 788aa54

3 files changed

+59
-7
lines changed

lib/IRGen/GenExistential.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ namespace {
247247

248248
void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T,
249249
bool isOutlined) const override {
250-
if (isOutlined) {
250+
if (isOutlined || T.hasLocalArchetype()) {
251251
Address destValue = projectValue(IGF, dest);
252252
Address srcValue = projectValue(IGF, src);
253253
asDerived().emitValueAssignWithCopy(IGF, destValue, srcValue);
@@ -262,7 +262,7 @@ namespace {
262262

263263
void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src,
264264
SILType T, bool isOutlined) const override {
265-
if (isOutlined) {
265+
if (isOutlined || T.hasLocalArchetype()) {
266266
Address destValue = projectValue(IGF, dest);
267267
Address srcValue = projectValue(IGF, src);
268268
asDerived().emitValueInitializeWithCopy(IGF, destValue, srcValue);
@@ -277,7 +277,7 @@ namespace {
277277

278278
void assignWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T,
279279
bool isOutlined) const override {
280-
if (isOutlined) {
280+
if (isOutlined || T.hasLocalArchetype()) {
281281
Address destValue = projectValue(IGF, dest);
282282
Address srcValue = projectValue(IGF, src);
283283
asDerived().emitValueAssignWithTake(IGF, destValue, srcValue);
@@ -292,7 +292,7 @@ namespace {
292292

293293
void initializeWithTake(IRGenFunction &IGF, Address dest, Address src,
294294
SILType T, bool isOutlined) const override {
295-
if (isOutlined) {
295+
if (isOutlined || T.hasLocalArchetype()) {
296296
Address destValue = projectValue(IGF, dest);
297297
Address srcValue = projectValue(IGF, src);
298298
asDerived().emitValueInitializeWithTake(IGF, destValue, srcValue);
@@ -307,7 +307,7 @@ namespace {
307307

308308
void destroy(IRGenFunction &IGF, Address existential, SILType T,
309309
bool isOutlined) const override {
310-
if (isOutlined) {
310+
if (isOutlined || T.hasLocalArchetype()) {
311311
Address valueAddr = projectValue(IGF, existential);
312312
asDerived().emitValueDestroy(IGF, valueAddr);
313313
} else {
@@ -955,7 +955,7 @@ class OpaqueExistentialTypeInfo final :
955955

956956
void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src,
957957
SILType T, bool isOutlined) const override {
958-
if (isOutlined) {
958+
if (isOutlined || T.hasLocalArchetype()) {
959959
llvm::Value *metadata = copyType(IGF, dest, src);
960960

961961
auto layout = getLayout();
@@ -977,7 +977,7 @@ class OpaqueExistentialTypeInfo final :
977977

978978
void initializeWithTake(IRGenFunction &IGF, Address dest, Address src,
979979
SILType T, bool isOutlined) const override {
980-
if (isOutlined) {
980+
if (isOutlined || T.hasLocalArchetype()) {
981981
// memcpy the existential container. This is safe because: either the
982982
// value is stored inline and is therefore by convention bitwise takable
983983
// or the value is stored in a reference counted heap buffer, in which
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking
2+
3+
public protocol P1<A> {
4+
associatedtype A
5+
}
6+
7+
public protocol P2<A>: class {
8+
associatedtype A
9+
}
10+
11+
public func f1<each T>(p: repeat any P1<each T>) {
12+
let _ = (repeat each p)
13+
}
14+
15+
public func f2<each T>(p: repeat any P2<each T>) {
16+
let _ = (repeat each p)
17+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking
2+
3+
public protocol P {}
4+
5+
extension P {
6+
@_transparent
7+
public func f() {
8+
let x: any Q<Self> = S<Self>()
9+
10+
// force a copy
11+
g(x, x)
12+
}
13+
}
14+
15+
@_optimize(none)
16+
public func g<T>(_: consuming T, _: consuming T) {}
17+
18+
public enum G<T> {
19+
case ok(String)
20+
case bar
21+
}
22+
23+
public func h(e: any P) {
24+
// We inline P.f(), because it is transparent, so we end
25+
// up working with an `any Q<@opened ...>`.
26+
e.f()
27+
}
28+
29+
public protocol Q<A> {
30+
associatedtype A
31+
}
32+
33+
public struct S<A>: Q {
34+
public init() {}
35+
}

0 commit comments

Comments
 (0)