diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index aa3956cb3185e..308ef99dc7163 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -754,6 +754,13 @@ class SILType { SILType subst(SILModule &M, SubstitutionMap subs, TypeExpansionContext context) const; + /// Strip concurrency annotations from the representation type. + SILType stripConcurrency(bool recursive, bool dropGlobalActor) { + auto strippedASTTy = getASTType()->stripConcurrency(recursive, dropGlobalActor); + return SILType::getPrimitiveType(strippedASTTy->getCanonicalType(), + getCategory()); + } + /// Return true if this type references a "ref" type that has a single pointer /// representation. Class existentials do not always qualify. bool isHeapObjectReferenceType() const; diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 15d8a550f0ab5..428b79a7c47f2 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -1967,15 +1967,21 @@ static void emitRawApply(SILGenFunction &SGF, SmallVector argValues; // Add the buffers for the indirect results if needed. -#ifndef NDEBUG - assert(indirectResultAddrs.size() == substFnConv.getNumIndirectSILResults()); unsigned resultIdx = 0; - for (auto indResultTy : - substFnConv.getIndirectSILResultTypes(SGF.getTypeExpansionContext())) { - assert(indResultTy == indirectResultAddrs[resultIdx++]->getType()); + for (auto indResultTy : substFnConv.getIndirectSILResultTypes(SGF.getTypeExpansionContext())) { + auto indResultAddr = indirectResultAddrs[resultIdx++]; + + if (indResultAddr->getType() != indResultTy) { + // Bitcast away differences in Sendable, global actor, etc. + if (indResultAddr->getType().stripConcurrency(/*recursive*/ true, /*dropGlobalActor*/ true) + == indResultTy.stripConcurrency(/*recursive*/ true, /*dropGlobalActor*/ true)) { + indResultAddr = SGF.B.createUncheckedAddrCast(loc, indResultAddr, indResultTy); + } + } + assert(indResultTy == indResultAddr->getType()); + + argValues.push_back(indResultAddr); } -#endif - argValues.append(indirectResultAddrs.begin(), indirectResultAddrs.end()); assert(!!indirectErrorAddr == substFnConv.hasIndirectSILErrorResults()); if (indirectErrorAddr) diff --git a/test/SILGen/preconcurrency_indirect_return.swift b/test/SILGen/preconcurrency_indirect_return.swift new file mode 100644 index 0000000000000..e5ceffe8a058d --- /dev/null +++ b/test/SILGen/preconcurrency_indirect_return.swift @@ -0,0 +1,10 @@ +// RUN: %target-swift-emit-silgen %s | %FileCheck %s + +@preconcurrency +func test() -> (any Sendable)? { nil } + +// CHECK-LABEL: sil {{.*}} @$s{{.*}}callWithPreconcurrency +func callWithPreconcurrency() { + // CHECK: unchecked_addr_cast {{.*}} to $*Optional + let x = test() +}