Skip to content

Commit f781ad3

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 { ... } } ```
1 parent b786c60 commit f781ad3

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
@@ -722,14 +722,14 @@ bool SILDeclRef::hasFuncDecl() const {
722722
}
723723

724724
ClosureExpr *SILDeclRef::getClosureExpr() const {
725-
return dyn_cast<ClosureExpr>(getAbstractClosureExpr());
725+
return dyn_cast_or_null<ClosureExpr>(getAbstractClosureExpr());
726726
}
727727
AutoClosureExpr *SILDeclRef::getAutoClosureExpr() const {
728-
return dyn_cast<AutoClosureExpr>(getAbstractClosureExpr());
728+
return dyn_cast_or_null<AutoClosureExpr>(getAbstractClosureExpr());
729729
}
730730

731731
FuncDecl *SILDeclRef::getFuncDecl() const {
732-
return dyn_cast<FuncDecl>(getDecl());
732+
return dyn_cast_or_null<FuncDecl>(getDecl());
733733
}
734734

735735
ModuleDecl *SILDeclRef::getModuleContext() const {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4004,6 +4004,16 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
40044004
CanAnyFunctionType funcTy;
40054005
if (auto *ACE = c.loc.dyn_cast<AbstractClosureExpr *>()) {
40064006
funcTy = cast<AnyFunctionType>(ACE->getType()->getCanonicalType());
4007+
4008+
// If we have a closure expr, see if we need to add Sendable to work
4009+
// issues with inheritActorContext and global actor isolation.
4010+
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
4011+
if (CE->inheritsActorContext() && CE->isBodyAsync() &&
4012+
CE->getActorIsolation().isActorIsolated() && !CE->isSendable()) {
4013+
auto newExtInfo = funcTy->getExtInfo().withSendable();
4014+
funcTy = funcTy.withExtInfo(newExtInfo);
4015+
}
4016+
}
40074017
} else {
40084018
funcTy = cast<AnyFunctionType>(vd->getInterfaceType()->getCanonicalType());
40094019
}

lib/SILGen/SILGenApply.cpp

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

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

1295-
auto closureType = cast<AnyFunctionType>(e->getType()->getCanonicalType());
1296-
SGF.SGM.emitClosure(e, SGF.getFunctionTypeInfo(closureType));
1312+
SGF.SGM.emitClosure(e, SGF.getClosureTypeInfo(e));
12971313

12981314
// If we're in top-level code, we don't need to physically capture script
12991315
// 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
@@ -521,7 +521,6 @@ namespace {
521521
RValue visitCaptureListExpr(CaptureListExpr *E, SGFContext C);
522522
RValue visitAbstractClosureExpr(AbstractClosureExpr *E, SGFContext C);
523523
ManagedValue tryEmitConvertedClosure(AbstractClosureExpr *e,
524-
CanAnyFunctionType closureType,
525524
const Conversion &conv);
526525
ManagedValue emitClosureReference(AbstractClosureExpr *e,
527526
const FunctionTypeInfo &contextInfo);
@@ -1809,9 +1808,7 @@ ManagedValue emitCFunctionPointer(SILGenFunction &SGF,
18091808
(void) emitAnyClosureExpr(SGF, semanticExpr,
18101809
[&](AbstractClosureExpr *closure) {
18111810
// Emit the closure body.
1812-
auto closureType =
1813-
cast<AnyFunctionType>(closure->getType()->getCanonicalType());
1814-
SGF.SGM.emitClosure(closure, SGF.getFunctionTypeInfo(closureType));
1811+
SGF.SGM.emitClosure(closure, SGF.getClosureTypeInfo(closure));
18151812

18161813
loc = closure;
18171814
return ManagedValue();
@@ -2960,10 +2957,10 @@ static bool canEmitSpecializedClosureFunction(CanAnyFunctionType closureType,
29602957

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

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

30293024
// Otherwise, emit the expression using the simple type of the expression.
3030-
auto info = SGF.getFunctionTypeInfo(closureType);
3025+
auto info = SGF.getClosureTypeInfo(e);
30313026
auto closure = emitClosureReference(e, info);
3032-
return RValue(SGF, e, closureType, closure);
3027+
3028+
return RValue(SGF, e, e->getType()->getCanonicalType(), closure);
30333029
}
30343030

30353031
ManagedValue

lib/SILGen/SILGenFunction.cpp

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

10391039
auto calleeConvention = ParameterConvention::Direct_Guaranteed;
10401040

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

10611080
return result;

lib/SILGen/SILGenFunction.h

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

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

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6530,6 +6530,7 @@ ManagedValue Transform::transformFunction(ManagedValue fn,
65306530
SILType resTy = SILType::getPrimitiveObjectType(expectedFnType);
65316531
fn = SGF.emitManagedRValueWithCleanup(
65326532
SGF.B.createThinToThickFunction(Loc, fn.forward(SGF), resTy));
6533+
65336534
} else if (newFnType != expectedFnType) {
65346535
// Escaping to noescape conversion.
65356536
SILType resTy = SILType::getPrimitiveObjectType(expectedFnType);

0 commit comments

Comments
 (0)