Skip to content

Commit 8ac81dc

Browse files
committed
SILGen: Bitcast indirect returns that differ only in concurrency annotations.
A call to a `@preconcurrency` function goes through a function conversion that removes `Sendable` from existentials among other things. Implement support for this by bitcasting indirect return slots whose type differs from the formal indirect return type in concurrency markings only. Fixes rdar://154240007
1 parent 6e8287c commit 8ac81dc

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

include/swift/SIL/SILType.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,13 @@ class SILType {
754754
SILType subst(SILModule &M, SubstitutionMap subs,
755755
TypeExpansionContext context) const;
756756

757+
/// Strip concurrency annotations from the representation type.
758+
SILType stripConcurrency(bool recursive, bool dropGlobalActor) {
759+
auto strippedASTTy = getASTType()->stripConcurrency(recursive, dropGlobalActor);
760+
return SILType::getPrimitiveType(strippedASTTy->getCanonicalType(),
761+
getCategory());
762+
}
763+
757764
/// Return true if this type references a "ref" type that has a single pointer
758765
/// representation. Class existentials do not always qualify.
759766
bool isHeapObjectReferenceType() const;

lib/SILGen/SILGenApply.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,15 +1966,21 @@ static void emitRawApply(SILGenFunction &SGF,
19661966
SmallVector<SILValue, 4> argValues;
19671967

19681968
// Add the buffers for the indirect results if needed.
1969-
#ifndef NDEBUG
1970-
assert(indirectResultAddrs.size() == substFnConv.getNumIndirectSILResults());
19711969
unsigned resultIdx = 0;
1972-
for (auto indResultTy :
1973-
substFnConv.getIndirectSILResultTypes(SGF.getTypeExpansionContext())) {
1974-
assert(indResultTy == indirectResultAddrs[resultIdx++]->getType());
1970+
for (auto indResultTy : substFnConv.getIndirectSILResultTypes(SGF.getTypeExpansionContext())) {
1971+
auto indResultAddr = indirectResultAddrs[resultIdx++];
1972+
1973+
if (indResultAddr->getType() != indResultTy) {
1974+
// Bitcast away differences in Sendable, global actor, etc.
1975+
if (indResultAddr->getType().stripConcurrency(/*recursive*/ true, /*dropGlobalActor*/ true)
1976+
== indResultTy.stripConcurrency(/*recursive*/ true, /*dropGlobalActor*/ true)) {
1977+
indResultAddr = SGF.B.createUncheckedAddrCast(loc, indResultAddr, indResultTy);
1978+
}
1979+
}
1980+
assert(indResultTy == indResultAddr->getType());
1981+
1982+
argValues.push_back(indResultAddr);
19751983
}
1976-
#endif
1977-
argValues.append(indirectResultAddrs.begin(), indirectResultAddrs.end());
19781984

19791985
assert(!!indirectErrorAddr == substFnConv.hasIndirectSILErrorResults());
19801986
if (indirectErrorAddr)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
@preconcurrency
4+
func test() -> (any Sendable)? { nil }
5+
6+
// CHECK-LABEL: sil {{.*}} @$s{{.*}}callWithPreconcurrency
7+
func callWithPreconcurrency() {
8+
// CHECK: unchecked_addr_cast {{.*}} to $*Optional<any Sendable>
9+
let x = test()
10+
}

0 commit comments

Comments
 (0)