Skip to content

Commit e156289

Browse files
authored
Merge pull request swiftlang#72126 from gottesmm/async-let-fixes
[region-isolation] Make async let closures non-Sendable and require actor isolation crossing function into an async let use a transferring result.
2 parents 10ac24d + acca735 commit e156289

15 files changed

+370
-131
lines changed

include/swift/AST/Builtins.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(GetCurrentAsyncTask, "getCurrentAsyncTask", "
884884
BUILTIN_MISC_OPERATION_WITH_SILGEN(CancelAsyncTask, "cancelAsyncTask", "", Special)
885885

886886
/// startAsyncLet()<T>: (
887-
/// __owned @Sendable @escaping () async throws -> T
887+
/// __owned @escaping () async throws -> transferring T
888888
/// ) -> Builtin.RawPointer
889889
///
890890
/// DEPRECATED. startAsyncLetWithLocalBuffer is used instead.
@@ -894,7 +894,7 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CancelAsyncTask, "cancelAsyncTask", "", Speci
894894
BUILTIN_MISC_OPERATION(StartAsyncLet, "startAsyncLet", "", Special)
895895

896896
/// startAsyncLetWithLocalBuffer()<T>: (
897-
/// __owned @Sendable @escaping () async throws -> T,
897+
/// __owned @escaping () async throws -> transferring T,
898898
/// _ resultBuf: Builtin.RawPointer
899899
/// ) -> Builtin.RawPointer
900900
///

include/swift/SIL/ApplySite.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -811,13 +811,18 @@ class FullApplySite : public ApplySite {
811811
}
812812
}
813813

814-
/// Return the applied argument without indirect results.
815-
unsigned getAppliedArgIndexWithoutIndirectResult(const Operand &oper) const {
814+
/// Return the applied argument index for the given operand ignoring indirect
815+
/// results.
816+
///
817+
/// So for instance:
818+
///
819+
/// apply %f(%result, %0, %1, %2, ...).
820+
unsigned getAppliedArgIndexWithoutIndirectResults(const Operand &oper) const {
816821
assert(oper.getUser() == **this);
817822
assert(isArgumentOperand(oper));
818823

819-
return oper.getOperandNumber() - getOperandIndexOfFirstArgument() -
820-
getNumIndirectSILResults() - getNumIndirectSILErrorResults();
824+
return getAppliedArgIndex(oper) - getNumIndirectSILResults() -
825+
getNumIndirectSILErrorResults();
821826
}
822827

823828
static FullApplySite getFromOpaqueValue(void *p) { return FullApplySite(p); }

include/swift/SIL/SILDeclRef.h

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ struct SILDeclRef {
197197
BackDeploymentKind backDeploymentKind : 2;
198198
/// The default argument index for a default argument getter.
199199
unsigned defaultArgIndex : 10;
200+
/// Set if this is for an async let closure.
201+
unsigned isAsyncLetClosure : 1;
200202

201203
PointerUnion<AutoDiffDerivativeFunctionIdentifier *,
202204
const GenericSignatureImpl *, CustomAttr *>
@@ -229,9 +231,10 @@ struct SILDeclRef {
229231

230232
/// Produces a null SILDeclRef.
231233
SILDeclRef()
232-
: loc(), kind(Kind::Func), isForeign(0),
233-
isDistributed(0), isKnownToBeLocal(0), isRuntimeAccessible(0),
234-
backDeploymentKind(BackDeploymentKind::None), defaultArgIndex(0) {}
234+
: loc(), kind(Kind::Func), isForeign(0), isDistributed(0),
235+
isKnownToBeLocal(0), isRuntimeAccessible(0),
236+
backDeploymentKind(BackDeploymentKind::None), defaultArgIndex(0),
237+
isAsyncLetClosure(0) {}
235238

236239
/// Produces a SILDeclRef of the given kind for the given decl.
237240
explicit SILDeclRef(
@@ -397,19 +400,18 @@ struct SILDeclRef {
397400

398401
/// Return the hash code for the SIL declaration.
399402
friend llvm::hash_code hash_value(const SILDeclRef &ref) {
400-
return llvm::hash_combine(ref.loc.getOpaqueValue(),
401-
static_cast<int>(ref.kind),
402-
ref.isForeign, ref.isDistributed,
403-
ref.defaultArgIndex);
403+
return llvm::hash_combine(
404+
ref.loc.getOpaqueValue(), static_cast<int>(ref.kind), ref.isForeign,
405+
ref.isDistributed, ref.defaultArgIndex, ref.isAsyncLetClosure);
404406
}
405407

406408
bool operator==(SILDeclRef rhs) const {
407409
return loc.getOpaqueValue() == rhs.loc.getOpaqueValue() &&
408410
kind == rhs.kind && isForeign == rhs.isForeign &&
409411
isDistributed == rhs.isDistributed &&
410412
backDeploymentKind == rhs.backDeploymentKind &&
411-
defaultArgIndex == rhs.defaultArgIndex &&
412-
pointer == rhs.pointer;
413+
defaultArgIndex == rhs.defaultArgIndex && pointer == rhs.pointer &&
414+
isAsyncLetClosure == rhs.isAsyncLetClosure;
413415
}
414416
bool operator!=(SILDeclRef rhs) const {
415417
return !(*this == rhs);
@@ -427,20 +429,17 @@ struct SILDeclRef {
427429
/*foreign=*/foreign,
428430
/*distributed=*/false,
429431
/*knownToBeLocal=*/false,
430-
/*runtimeAccessible=*/false,
431-
backDeploymentKind,
432-
defaultArgIndex,
432+
/*runtimeAccessible=*/false, backDeploymentKind,
433+
defaultArgIndex, isAsyncLetClosure,
433434
pointer.get<AutoDiffDerivativeFunctionIdentifier *>());
434435
}
435436
/// Returns the distributed entry point corresponding to the same decl.
436437
SILDeclRef asDistributed(bool distributed = true) const {
437438
return SILDeclRef(loc.getOpaqueValue(), kind,
438439
/*foreign=*/false,
439440
/*distributed=*/distributed,
440-
/*knownToBeLocal=*/false,
441-
isRuntimeAccessible,
442-
backDeploymentKind,
443-
defaultArgIndex,
441+
/*knownToBeLocal=*/false, isRuntimeAccessible,
442+
backDeploymentKind, defaultArgIndex, isAsyncLetClosure,
444443
pointer.get<AutoDiffDerivativeFunctionIdentifier *>());
445444
}
446445

@@ -451,9 +450,8 @@ struct SILDeclRef {
451450
/*foreign=*/false,
452451
/*distributed=*/false,
453452
/*distributedKnownToBeLocal=*/isLocal,
454-
isRuntimeAccessible,
455-
backDeploymentKind,
456-
defaultArgIndex,
453+
isRuntimeAccessible, backDeploymentKind, defaultArgIndex,
454+
isAsyncLetClosure,
457455
pointer.get<AutoDiffDerivativeFunctionIdentifier *>());
458456
}
459457

@@ -466,13 +464,9 @@ struct SILDeclRef {
466464

467465
/// Returns a copy of the decl with the given back deployment kind.
468466
SILDeclRef asBackDeploymentKind(BackDeploymentKind backDeploymentKind) const {
469-
return SILDeclRef(loc.getOpaqueValue(), kind,
470-
isForeign,
471-
isDistributed,
472-
isKnownToBeLocal,
473-
isRuntimeAccessible,
474-
backDeploymentKind,
475-
defaultArgIndex,
467+
return SILDeclRef(loc.getOpaqueValue(), kind, isForeign, isDistributed,
468+
isKnownToBeLocal, isRuntimeAccessible, backDeploymentKind,
469+
defaultArgIndex, isAsyncLetClosure,
476470
pointer.get<AutoDiffDerivativeFunctionIdentifier *>());
477471
}
478472

@@ -606,21 +600,18 @@ struct SILDeclRef {
606600
private:
607601
friend struct llvm::DenseMapInfo<swift::SILDeclRef>;
608602
/// Produces a SILDeclRef from an opaque value.
609-
explicit SILDeclRef(void *opaqueLoc, Kind kind,
610-
bool isForeign,
611-
bool isDistributed,
612-
bool isKnownToBeLocal,
603+
explicit SILDeclRef(void *opaqueLoc, Kind kind, bool isForeign,
604+
bool isDistributed, bool isKnownToBeLocal,
613605
bool isRuntimeAccessible,
614606
BackDeploymentKind backDeploymentKind,
615-
unsigned defaultArgIndex,
607+
unsigned defaultArgIndex, bool isAsyncLetClosure,
616608
AutoDiffDerivativeFunctionIdentifier *derivativeId)
617609
: loc(Loc::getFromOpaqueValue(opaqueLoc)), kind(kind),
618-
isForeign(isForeign),
619-
isDistributed(isDistributed),
610+
isForeign(isForeign), isDistributed(isDistributed),
620611
isKnownToBeLocal(isKnownToBeLocal),
621612
isRuntimeAccessible(isRuntimeAccessible),
622613
backDeploymentKind(backDeploymentKind),
623-
defaultArgIndex(defaultArgIndex),
614+
defaultArgIndex(defaultArgIndex), isAsyncLetClosure(isAsyncLetClosure),
624615
pointer(derivativeId) {}
625616
};
626617

@@ -644,11 +635,13 @@ template<> struct DenseMapInfo<swift::SILDeclRef> {
644635

645636
static SILDeclRef getEmptyKey() {
646637
return SILDeclRef(PointerInfo::getEmptyKey(), Kind::Func, false, false,
647-
false, false, BackDeploymentKind::None, 0, nullptr);
638+
false, false, BackDeploymentKind::None, 0, false,
639+
nullptr);
648640
}
649641
static SILDeclRef getTombstoneKey() {
650642
return SILDeclRef(PointerInfo::getTombstoneKey(), Kind::Func, false, false,
651-
false, false, BackDeploymentKind::None, 0, nullptr);
643+
false, false, BackDeploymentKind::None, 0, false,
644+
nullptr);
652645
}
653646
static unsigned getHashValue(swift::SILDeclRef Val) {
654647
unsigned h1 = PointerInfo::getHashValue(Val.loc.getOpaqueValue());

lib/AST/Builtins.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,8 +1639,23 @@ static ValueDecl *getStartAsyncLet(ASTContext &ctx, Identifier id) {
16391639
// TaskOptionRecord*
16401640
builder.addParameter(makeConcrete(OptionalType::get(ctx.TheRawPointerType)));
16411641

1642-
// operation async function pointer: () async throws -> T
1643-
auto extInfo = ASTExtInfoBuilder().withAsync().withThrows().withNoEscape().build();
1642+
// If transferring results are enabled, make async let return a transferring
1643+
// value.
1644+
//
1645+
// NOTE: If our actual returned function does not return something that is
1646+
// transferring, we will emit an error in Sema. In the case of SILGen, we just
1647+
// in such a case want to thunk and not emit an error. So in such a case, we
1648+
// always make this builtin take a transferring result.
1649+
bool hasTransferringResult =
1650+
ctx.LangOpts.hasFeature(Feature::TransferringArgsAndResults);
1651+
1652+
// operation async function pointer: () async throws -> transferring T
1653+
auto extInfo = ASTExtInfoBuilder()
1654+
.withAsync()
1655+
.withThrows()
1656+
.withNoEscape()
1657+
.withTransferringResult(hasTransferringResult)
1658+
.build();
16441659
builder.addParameter(
16451660
makeConcrete(FunctionType::get({ }, genericParam, extInfo)));
16461661

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,17 @@ SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind, bool isForeign,
127127
bool isRuntimeAccessible,
128128
SILDeclRef::BackDeploymentKind backDeploymentKind,
129129
AutoDiffDerivativeFunctionIdentifier *derivativeId)
130-
: loc(vd), kind(kind), isForeign(isForeign),
131-
isDistributed(isDistributed), isKnownToBeLocal(isKnownToBeLocal),
130+
: loc(vd), kind(kind), isForeign(isForeign), isDistributed(isDistributed),
131+
isKnownToBeLocal(isKnownToBeLocal),
132132
isRuntimeAccessible(isRuntimeAccessible),
133133
backDeploymentKind(backDeploymentKind), defaultArgIndex(0),
134-
pointer(derivativeId) {}
134+
isAsyncLetClosure(0), pointer(derivativeId) {}
135135

136136
SILDeclRef::SILDeclRef(SILDeclRef::Loc baseLoc, bool asForeign,
137137
bool asDistributed, bool asDistributedKnownToBeLocal)
138138
: isRuntimeAccessible(false),
139139
backDeploymentKind(SILDeclRef::BackDeploymentKind::None),
140-
defaultArgIndex(0),
140+
defaultArgIndex(0), isAsyncLetClosure(0),
141141
pointer((AutoDiffDerivativeFunctionIdentifier *)nullptr) {
142142
if (auto *vd = baseLoc.dyn_cast<ValueDecl*>()) {
143143
if (auto *fd = dyn_cast<FuncDecl>(vd)) {
@@ -170,6 +170,13 @@ SILDeclRef::SILDeclRef(SILDeclRef::Loc baseLoc, bool asForeign,
170170
} else if (auto *ACE = baseLoc.dyn_cast<AbstractClosureExpr *>()) {
171171
loc = ACE;
172172
kind = Kind::Func;
173+
if (ACE->getASTContext().LangOpts.hasFeature(
174+
Feature::TransferringArgsAndResults)) {
175+
if (auto *autoClosure = dyn_cast<AutoClosureExpr>(ACE)) {
176+
isAsyncLetClosure =
177+
autoClosure->getThunkKind() == AutoClosureExpr::Kind::AsyncLet;
178+
}
179+
}
173180
} else {
174181
llvm_unreachable("impossible SILDeclRef loc");
175182
}

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,6 +1998,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19981998
convention = ParameterConvention::Direct_Guaranteed;
19991999
}
20002000
SILParameterInfo param(loweredTy.getASTType(), convention, options);
2001+
if (function.isAsyncLetClosure)
2002+
param = param.addingOption(SILParameterInfo::Transferring);
20012003
inputs.push_back(param);
20022004
break;
20032005
}
@@ -2013,6 +2015,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20132015
/*mutable*/ true);
20142016
auto convention = ParameterConvention::Direct_Guaranteed;
20152017
auto param = SILParameterInfo(boxTy, convention, options);
2018+
if (function.isAsyncLetClosure)
2019+
param = param.addingOption(SILParameterInfo::Transferring);
20162020
inputs.push_back(param);
20172021
break;
20182022
}
@@ -2028,6 +2032,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20282032
/*mutable*/ false);
20292033
auto convention = ParameterConvention::Direct_Guaranteed;
20302034
auto param = SILParameterInfo(boxTy, convention, options);
2035+
if (function.isAsyncLetClosure)
2036+
param = param.addingOption(SILParameterInfo::Transferring);
20312037
inputs.push_back(param);
20322038
break;
20332039
}
@@ -2037,6 +2043,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20372043
auto param = SILParameterInfo(
20382044
ty.getASTType(), ParameterConvention::Indirect_InoutAliasable,
20392045
options);
2046+
if (function.isAsyncLetClosure)
2047+
param = param.addingOption(SILParameterInfo::Transferring);
20402048
inputs.push_back(param);
20412049
break;
20422050
}
@@ -2047,6 +2055,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20472055
auto param = SILParameterInfo(ty.getASTType(),
20482056
ParameterConvention::Indirect_In_Guaranteed,
20492057
options);
2058+
if (function.isAsyncLetClosure)
2059+
param = param.addingOption(SILParameterInfo::Transferring);
20502060
inputs.push_back(param);
20512061
break;
20522062
}

0 commit comments

Comments
 (0)