Skip to content

Commit 6b32fba

Browse files
committed
[sending] Compensate in SILGen for a typechecker bug where we do not properly mark actor isolated async closures passed to an inheritActorContext argument as being Sendable.
The reason why I am fixing this is that otherwise, we get a warning when one creates an actor isolated closure and pass it into a task, e.x.: ```swift @mainactor func test() { // We would get a warning on the closure below saying that we are sending // a closure that is MainActor isolated. Task { ... } } ``` (cherry picked from commit f781ad3)
1 parent 5d9aa90 commit 6b32fba

File tree

8 files changed

+409
-45
lines changed

8 files changed

+409
-45
lines changed

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -721,14 +721,14 @@ bool SILDeclRef::hasFuncDecl() const {
721721
}
722722

723723
ClosureExpr *SILDeclRef::getClosureExpr() const {
724-
return dyn_cast<ClosureExpr>(getAbstractClosureExpr());
724+
return dyn_cast_or_null<ClosureExpr>(getAbstractClosureExpr());
725725
}
726726
AutoClosureExpr *SILDeclRef::getAutoClosureExpr() const {
727-
return dyn_cast<AutoClosureExpr>(getAbstractClosureExpr());
727+
return dyn_cast_or_null<AutoClosureExpr>(getAbstractClosureExpr());
728728
}
729729

730730
FuncDecl *SILDeclRef::getFuncDecl() const {
731-
return dyn_cast<FuncDecl>(getDecl());
731+
return dyn_cast_or_null<FuncDecl>(getDecl());
732732
}
733733

734734
ModuleDecl *SILDeclRef::getModuleContext() const {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3992,6 +3992,16 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
39923992
CanAnyFunctionType funcTy;
39933993
if (auto *ACE = c.loc.dyn_cast<AbstractClosureExpr *>()) {
39943994
funcTy = cast<AnyFunctionType>(ACE->getType()->getCanonicalType());
3995+
3996+
// If we have a closure expr, see if we need to add Sendable to work
3997+
// issues with inheritActorContext and global actor isolation.
3998+
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
3999+
if (CE->inheritsActorContext() && CE->isBodyAsync() &&
4000+
CE->getActorIsolation().isActorIsolated() && !CE->isSendable()) {
4001+
auto newExtInfo = funcTy->getExtInfo().withSendable();
4002+
funcTy = funcTy.withExtInfo(newExtInfo);
4003+
}
4004+
}
39954005
} else {
39964006
funcTy = cast<AnyFunctionType>(vd->getInterfaceType()->getCanonicalType());
39974007
}

lib/SILGen/SILGenApply.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ using namespace Lowering;
5656
// Utility Functions
5757
//===----------------------------------------------------------------------===//
5858

59+
FunctionTypeInfo SILGenFunction::getClosureTypeInfo(AbstractClosureExpr *expr) {
60+
auto fnType = cast<AnyFunctionType>(expr->getType()->getCanonicalType());
61+
62+
// If we have a closure expr that has inherits actor context, work around AST
63+
// issues that causes us to be able to get non-Sendable actor isolated
64+
// closures.
65+
if (auto *ce = dyn_cast<ClosureExpr>(expr)) {
66+
if (ce->inheritsActorContext() && fnType->isAsync() &&
67+
!fnType->isSendable() && expr->getActorIsolation().isActorIsolated()) {
68+
auto newExtInfo = fnType->getExtInfo().withSendable();
69+
fnType = fnType.withExtInfo(newExtInfo);
70+
}
71+
}
72+
73+
return getFunctionTypeInfo(fnType);
74+
}
75+
5976
FunctionTypeInfo SILGenFunction::getFunctionTypeInfo(CanAnyFunctionType fnType) {
6077
return { AbstractionPattern(fnType), fnType,
6178
cast<SILFunctionType>(getLoweredRValueType(fnType)) };
@@ -1355,8 +1372,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
13551372
void visitAbstractClosureExpr(AbstractClosureExpr *e) {
13561373
SILDeclRef constant(e);
13571374

1358-
auto closureType = cast<AnyFunctionType>(e->getType()->getCanonicalType());
1359-
SGF.SGM.emitClosure(e, SGF.getFunctionTypeInfo(closureType));
1375+
SGF.SGM.emitClosure(e, SGF.getClosureTypeInfo(e));
13601376

13611377
// If we're in top-level code, we don't need to physically capture script
13621378
// globals, but we still need to mark them as escaping so that DI can flag

lib/SILGen/SILGenExpr.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,6 @@ namespace {
520520
RValue visitCaptureListExpr(CaptureListExpr *E, SGFContext C);
521521
RValue visitAbstractClosureExpr(AbstractClosureExpr *E, SGFContext C);
522522
ManagedValue tryEmitConvertedClosure(AbstractClosureExpr *e,
523-
CanAnyFunctionType closureType,
524523
const Conversion &conv);
525524
ManagedValue emitClosureReference(AbstractClosureExpr *e,
526525
const FunctionTypeInfo &contextInfo);
@@ -1808,9 +1807,7 @@ ManagedValue emitCFunctionPointer(SILGenFunction &SGF,
18081807
(void) emitAnyClosureExpr(SGF, semanticExpr,
18091808
[&](AbstractClosureExpr *closure) {
18101809
// Emit the closure body.
1811-
auto closureType =
1812-
cast<AnyFunctionType>(closure->getType()->getCanonicalType());
1813-
SGF.SGM.emitClosure(closure, SGF.getFunctionTypeInfo(closureType));
1810+
SGF.SGM.emitClosure(closure, SGF.getClosureTypeInfo(closure));
18141811

18151812
loc = closure;
18161813
return ManagedValue();
@@ -2959,10 +2956,10 @@ static bool canEmitSpecializedClosureFunction(CanAnyFunctionType closureType,
29592956

29602957
/// Try to emit the given closure under the given conversion.
29612958
/// Returns an invalid ManagedValue if this fails.
2962-
ManagedValue
2963-
RValueEmitter::tryEmitConvertedClosure(AbstractClosureExpr *e,
2964-
CanAnyFunctionType closureType,
2965-
const Conversion &conv) {
2959+
ManagedValue RValueEmitter::tryEmitConvertedClosure(AbstractClosureExpr *e,
2960+
const Conversion &conv) {
2961+
auto closureType = cast<AnyFunctionType>(e->getType()->getCanonicalType());
2962+
29662963
// Bail out if we don't have specialized type information from context.
29672964
auto info = tryGetSpecializedClosureTypeFromContext(closureType, conv);
29682965
if (!info) return ManagedValue();
@@ -3011,13 +3008,11 @@ RValue RValueEmitter::visitAbstractClosureExpr(AbstractClosureExpr *e,
30113008
if (auto *placeholder = wrappedValueAutoclosurePlaceholder(e))
30123009
return visitPropertyWrapperValuePlaceholderExpr(placeholder, C);
30133010

3014-
auto closureType = cast<AnyFunctionType>(e->getType()->getCanonicalType());
3015-
30163011
// If we're emitting into a converting context, try to combine the
30173012
// conversion into the emission of the closure function.
30183013
if (auto *convertingInit = C.getAsConversion()) {
3019-
ManagedValue closure = tryEmitConvertedClosure(e, closureType,
3020-
convertingInit->getConversion());
3014+
ManagedValue closure =
3015+
tryEmitConvertedClosure(e, convertingInit->getConversion());
30213016
if (closure.isValid()) {
30223017
convertingInit->initWithConvertedValue(SGF, e, closure);
30233018
convertingInit->finishInitialization(SGF);
@@ -3026,9 +3021,10 @@ RValue RValueEmitter::visitAbstractClosureExpr(AbstractClosureExpr *e,
30263021
}
30273022

30283023
// Otherwise, emit the expression using the simple type of the expression.
3029-
auto info = SGF.getFunctionTypeInfo(closureType);
3024+
auto info = SGF.getClosureTypeInfo(e);
30303025
auto closure = emitClosureReference(e, info);
3031-
return RValue(SGF, e, closureType, closure);
3026+
3027+
return RValue(SGF, e, e->getType()->getCanonicalType(), closure);
30323028
}
30333029

30343030
ManagedValue

lib/SILGen/SILGenFunction.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,10 +1037,9 @@ SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant,
10371037

10381038
auto calleeConvention = ParameterConvention::Direct_Guaranteed;
10391039

1040-
auto resultIsolation = (hasErasedIsolation
1041-
? SILFunctionTypeIsolation::Erased
1042-
: SILFunctionTypeIsolation::Unknown);
1043-
1040+
auto resultIsolation =
1041+
(hasErasedIsolation ? SILFunctionTypeIsolation::Erased
1042+
: SILFunctionTypeIsolation::Unknown);
10441043
auto toClosure =
10451044
B.createPartialApply(loc, functionRef, subs, forwardedArgs,
10461045
calleeConvention, resultIsolation);
@@ -1055,6 +1054,26 @@ SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant,
10551054
typeContext.OrigType,
10561055
typeContext.FormalType,
10571056
SILType::getPrimitiveObjectType(typeContext.ExpectedLoweredType));
1057+
1058+
auto resultType = cast<SILFunctionType>(result.getType().getASTType());
1059+
1060+
// Check if we performed Sendable/sending type compensation in
1061+
// emitTransformedValue for a closure. If we did, insert some fixup code to
1062+
// convert from an @Sendable to a not-@Sendable value.
1063+
//
1064+
// DISCUSSION: We cannot do this internally to emitTransformedValue since it
1065+
// does not have access to our SILDeclRef.
1066+
if (auto *e = constant.getClosureExpr()) {
1067+
auto actualType = cast<AnyFunctionType>(e->getType()->getCanonicalType());
1068+
if (e->inheritsActorContext() &&
1069+
e->getActorIsolation().isActorIsolated() && actualType->isAsync() &&
1070+
!actualType->isSendable() && resultType->isSendable()) {
1071+
auto extInfo = resultType->getExtInfo().withSendable(false);
1072+
resultType = resultType->getWithExtInfo(extInfo);
1073+
result = B.createConvertFunction(
1074+
loc, result, SILType::getPrimitiveObjectType(resultType));
1075+
}
1076+
}
10581077
}
10591078

10601079
return result;

lib/SILGen/SILGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
728728
/// without any contextual overrides.
729729
FunctionTypeInfo getFunctionTypeInfo(CanAnyFunctionType fnType);
730730

731+
/// A helper method that calls getFunctionTypeInfo that also marks global
732+
/// actor isolated async closures that are not sendable as sendable.
733+
FunctionTypeInfo getClosureTypeInfo(AbstractClosureExpr *expr);
734+
731735
bool isEmittingTopLevelCode() { return IsEmittingTopLevelCode; }
732736
void stopEmittingTopLevelCode() { IsEmittingTopLevelCode = false; }
733737

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6526,6 +6526,7 @@ ManagedValue Transform::transformFunction(ManagedValue fn,
65266526
SILType resTy = SILType::getPrimitiveObjectType(expectedFnType);
65276527
fn = SGF.emitManagedRValueWithCleanup(
65286528
SGF.B.createThinToThickFunction(Loc, fn.forward(SGF), resTy));
6529+
65296530
} else if (newFnType != expectedFnType) {
65306531
// Escaping to noescape conversion.
65316532
SILType resTy = SILType::getPrimitiveObjectType(expectedFnType);

0 commit comments

Comments
 (0)