Skip to content

Commit 3b62296

Browse files
authored
Merge pull request #36907 from DougGregor/global-actor-function-type-isolation
2 parents 80fe825 + 3dc65c6 commit 3b62296

26 files changed

+460
-185
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4385,6 +4385,12 @@ ERROR(global_actor_from_nonactor_context,none,
43854385
"%0 %1 isolated to global actor %2 can not be %select{referenced|mutated|used 'inout'}4"
43864386
" from %select{this|a non-isolated}3%select{| synchronous}5 context",
43874387
(DescriptiveDeclKind, DeclName, Type, bool, unsigned, bool))
4388+
ERROR(actor_isolated_call,none,
4389+
"call to %0 function in a synchronous %1 context",
4390+
(ActorIsolation, ActorIsolation))
4391+
ERROR(actor_isolated_call_decl,none,
4392+
"call to %0 %1 %2 in a synchronous %3 context",
4393+
(ActorIsolation, DescriptiveDeclKind, DeclName, ActorIsolation))
43884394
ERROR(actor_isolated_partial_apply,none,
43894395
"actor-isolated %0 %1 can not be partially applied",
43904396
(DescriptiveDeclKind, DeclName))

lib/AST/ASTContext.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3075,11 +3075,13 @@ DynamicSelfType *DynamicSelfType::get(Type selfType, const ASTContext &ctx) {
30753075

30763076
static RecursiveTypeProperties
30773077
getFunctionRecursiveProperties(ArrayRef<AnyFunctionType::Param> params,
3078-
Type result) {
3078+
Type result, Type globalActor) {
30793079
RecursiveTypeProperties properties;
30803080
for (auto param : params)
30813081
properties |= param.getPlainType()->getRecursiveProperties();
30823082
properties |= result->getRecursiveProperties();
3083+
if (globalActor)
3084+
properties |= globalActor->getRecursiveProperties();
30833085
properties &= ~RecursiveTypeProperties::IsLValue;
30843086
return properties;
30853087
}
@@ -3274,7 +3276,11 @@ void FunctionType::Profile(llvm::FoldingSetNodeID &ID,
32743276

32753277
FunctionType *FunctionType::get(ArrayRef<AnyFunctionType::Param> params,
32763278
Type result, Optional<ExtInfo> info) {
3277-
auto properties = getFunctionRecursiveProperties(params, result);
3279+
Type globalActor;
3280+
if (info.hasValue())
3281+
globalActor = info->getGlobalActor();
3282+
3283+
auto properties = getFunctionRecursiveProperties(params, result, globalActor);
32783284
auto arena = getArena(properties);
32793285

32803286
llvm::FoldingSetNodeID id;
@@ -3296,10 +3302,6 @@ FunctionType *FunctionType::get(ArrayRef<AnyFunctionType::Param> params,
32963302
bool hasClangInfo =
32973303
info.hasValue() && !info.getValue().getClangTypeInfo().empty();
32983304

3299-
Type globalActor;
3300-
if (info.hasValue())
3301-
globalActor = info->getGlobalActor();
3302-
33033305
size_t allocSize = totalSizeToAlloc<
33043306
AnyFunctionType::Param, ClangTypeInfo, Type
33053307
>(params.size(), hasClangInfo ? 1 : 0, globalActor ? 1 : 0);
@@ -3393,7 +3395,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature sig,
33933395
if (info.hasValue())
33943396
globalActor = info->getGlobalActor();
33953397

3396-
if (globalActor && !globalActor->isCanonical())
3398+
if (globalActor && !sig->isCanonicalTypeInContext(globalActor))
33973399
isCanonical = false;
33983400

33993401
size_t allocSize = totalSizeToAlloc<AnyFunctionType::Param, Type>(

lib/AST/DiagnosticEngine.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,18 @@ static Type getAkaTypeForDisplay(Type type) {
475475
});
476476
}
477477

478+
/// Determine whether this is the main actor type.
479+
static bool isMainActor(Type type) {
480+
if (auto nominal = type->getAnyNominal()) {
481+
if (nominal->getName().is("MainActor") &&
482+
nominal->getParentModule()->getName() ==
483+
nominal->getASTContext().Id_Concurrency)
484+
return true;
485+
}
486+
487+
return false;
488+
}
489+
478490
/// Format a single diagnostic argument and write it to the given
479491
/// stream.
480492
static void formatDiagnosticArgument(StringRef Modifier,
@@ -710,18 +722,21 @@ static void formatDiagnosticArgument(StringRef Modifier,
710722
break;
711723

712724
case ActorIsolation::GlobalActor:
713-
case ActorIsolation::GlobalActorUnsafe:
714-
Out << "global actor " << FormatOpts.OpeningQuotationMark
715-
<< isolation.getGlobalActor().getString()
716-
<< FormatOpts.ClosingQuotationMark << "-isolated";
725+
case ActorIsolation::GlobalActorUnsafe: {
726+
Type globalActor = isolation.getGlobalActor();
727+
if (isMainActor(globalActor)) {
728+
Out << "main actor-isolated";
729+
} else {
730+
Out << "global actor " << FormatOpts.OpeningQuotationMark
731+
<< globalActor.getString()
732+
<< FormatOpts.ClosingQuotationMark << "-isolated";
733+
}
717734
break;
735+
}
718736

719737
case ActorIsolation::Independent:
720-
Out << "actor-independent";
721-
break;
722-
723738
case ActorIsolation::Unspecified:
724-
Out << "unspecified";
739+
Out << "nonisolated";
725740
break;
726741
}
727742
}

lib/AST/Type.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4884,6 +4884,17 @@ case TypeKind::Id:
48844884
if (resultTy.getPointer() != function->getResult().getPointer())
48854885
isUnchanged = false;
48864886

4887+
// Transform the global actor.
4888+
Type globalActorType;
4889+
if (Type origGlobalActorType = function->getGlobalActor()) {
4890+
globalActorType = origGlobalActorType.transformRec(fn);
4891+
if (!globalActorType)
4892+
return Type();
4893+
4894+
if (globalActorType.getPointer() != origGlobalActorType.getPointer())
4895+
isUnchanged = false;
4896+
}
4897+
48874898
if (auto genericFnType = dyn_cast<GenericFunctionType>(base)) {
48884899
#ifndef NDEBUG
48894900
// Check that generic parameters won't be trasnformed.
@@ -4900,15 +4911,17 @@ case TypeKind::Id:
49004911
if (!function->hasExtInfo())
49014912
return GenericFunctionType::get(genericSig, substParams, resultTy);
49024913
return GenericFunctionType::get(genericSig, substParams, resultTy,
4903-
function->getExtInfo());
4914+
function->getExtInfo()
4915+
.withGlobalActor(globalActorType));
49044916
}
49054917

49064918
if (isUnchanged) return *this;
49074919

49084920
if (!function->hasExtInfo())
49094921
return FunctionType::get(substParams, resultTy);
49104922
return FunctionType::get(substParams, resultTy,
4911-
function->getExtInfo());
4923+
function->getExtInfo()
4924+
.withGlobalActor(globalActorType));
49124925
}
49134926

49144927
case TypeKind::ArraySlice: {

lib/SILGen/SILGenApply.cpp

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3651,15 +3651,15 @@ class CallEmission {
36513651

36523652
Callee callee;
36533653
FormalEvaluationScope initialWritebackScope;
3654-
bool implicitlyAsync;
3654+
Optional<ActorIsolation> implicitAsyncIsolation;
36553655

36563656
public:
36573657
/// Create an emission for a call of the given callee.
36583658
CallEmission(SILGenFunction &SGF, Callee &&callee,
36593659
FormalEvaluationScope &&writebackScope)
36603660
: SGF(SGF), callee(std::move(callee)),
36613661
initialWritebackScope(std::move(writebackScope)),
3662-
implicitlyAsync(false) {}
3662+
implicitAsyncIsolation(None) {}
36633663

36643664
/// A factory method for decomposing the apply expr \p e into a call
36653665
/// emission.
@@ -3699,7 +3699,9 @@ class CallEmission {
36993699
/// Sets a flag that indicates whether this call be treated as being
37003700
/// implicitly async, i.e., it requires a hop_to_executor prior to
37013701
/// invoking the sync callee, etc.
3702-
void setImplicitlyAsync(bool flag) { implicitlyAsync = flag; }
3702+
void setImplicitlyAsync(Optional<ActorIsolation> implicitAsyncIsolation) {
3703+
this->implicitAsyncIsolation = implicitAsyncIsolation;
3704+
}
37033705

37043706
CleanupHandle applyCoroutine(SmallVectorImpl<ManagedValue> &yields);
37053707

@@ -3920,15 +3922,11 @@ RValue CallEmission::applyNormalCall(SGFContext C) {
39203922

39213923
auto mv = callee.getFnValue(SGF, borrowedSelf);
39223924

3923-
Optional<ValueDecl*> calleeDeclInfo;
3924-
if (implicitlyAsync)
3925-
calleeDeclInfo = callee.getDecl();
3926-
39273925
// Emit the uncurried call.
39283926
return SGF.emitApply(
39293927
std::move(resultPlan), std::move(argScope), uncurriedLoc.getValue(), mv,
39303928
callee.getSubstitutions(), uncurriedArgs, calleeTypeInfo, options,
3931-
uncurriedContext, calleeDeclInfo);
3929+
uncurriedContext, implicitAsyncIsolation);
39323930
}
39333931

39343932
static void emitPseudoFunctionArguments(SILGenFunction &SGF,
@@ -4243,7 +4241,28 @@ CallEmission CallEmission::forApplyExpr(SILGenFunction &SGF, ApplyExpr *e) {
42434241
apply.callSite->isNoThrows(),
42444242
apply.callSite->isNoAsync());
42454243

4246-
emission.setImplicitlyAsync(apply.callSite->implicitlyAsync());
4244+
// For an implicitly-async call, determine the actor isolation.
4245+
if (apply.callSite->implicitlyAsync()) {
4246+
Optional<ActorIsolation> isolation;
4247+
4248+
// Check for global-actor isolation on the function type.
4249+
if (auto fnType = apply.callSite->getFn()->getType()
4250+
->castTo<FunctionType>()) {
4251+
if (Type globalActor = fnType->getGlobalActor()) {
4252+
isolation = ActorIsolation::forGlobalActor(globalActor, false);
4253+
}
4254+
}
4255+
4256+
// If there was no global-actor isolation on the function type, find
4257+
// the callee declaration and retrieve the isolation from it.
4258+
if (!isolation) {
4259+
if (auto decl = emission.callee.getDecl())
4260+
isolation = getActorIsolation(decl);
4261+
}
4262+
4263+
assert(isolation && "Implicitly asynchronous call without isolation");
4264+
emission.setImplicitlyAsync(isolation);
4265+
}
42474266
}
42484267

42494268
return emission;
@@ -4302,7 +4321,7 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
43024321
ArrayRef<ManagedValue> args,
43034322
const CalleeTypeInfo &calleeTypeInfo,
43044323
ApplyOptions options, SGFContext evalContext,
4305-
Optional<ValueDecl *> implicitlyAsyncApply) {
4324+
Optional<ActorIsolation> implicitAsyncIsolation) {
43064325
auto substFnType = calleeTypeInfo.substFnType;
43074326
auto substResultType = calleeTypeInfo.substResultType;
43084327

@@ -4390,22 +4409,27 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
43904409

43914410
ExecutorBreadcrumb breadcrumb;
43924411

4393-
// The presence of `implicitlyAsyncApply` indicates that the callee is a
4412+
// The presence of `implicitAsyncIsolation` indicates that the callee is a
43944413
// synchronous function isolated to an actor other than our own.
43954414
// Such functions require the caller to hop to the callee's executor
43964415
// prior to invoking the callee.
4397-
if (implicitlyAsyncApply.hasValue()) {
4416+
if (implicitAsyncIsolation) {
43984417
assert(F.isAsync() && "cannot hop_to_executor in a non-async func!");
43994418

4400-
auto calleeVD = implicitlyAsyncApply.getValue();
4401-
if (auto *funcDecl = dyn_cast_or_null<AbstractFunctionDecl>(calleeVD)) {
4402-
Optional<ManagedValue> actorSelf;
4419+
switch (*implicitAsyncIsolation) {
4420+
case ActorIsolation::ActorInstance:
4421+
breadcrumb = emitHopToTargetActor(loc, *implicitAsyncIsolation,
4422+
args.back());
4423+
break;
44034424

4404-
if (args.size() > 0)
4405-
actorSelf = args.back();
4425+
case ActorIsolation::GlobalActor:
4426+
case ActorIsolation::GlobalActorUnsafe:
4427+
breadcrumb = emitHopToTargetActor(loc, *implicitAsyncIsolation, None);
4428+
break;
44064429

4407-
breadcrumb = emitHopToTargetActor(loc, getActorIsolation(funcDecl),
4408-
actorSelf);
4430+
case ActorIsolation::Independent:
4431+
case ActorIsolation::Unspecified:
4432+
llvm_unreachable("Not actor-isolated");
44094433
}
44104434
} else if (ExpectedExecutor && substFnType->isAsync()) {
44114435
// Otherwise, if we're in an actor method ourselves, and we're calling into

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
15841584
ArrayRef<ManagedValue> args,
15851585
const CalleeTypeInfo &calleeTypeInfo, ApplyOptions options,
15861586
SGFContext evalContext,
1587-
Optional<ValueDecl *> implicitlyAsyncApply);
1587+
Optional<ActorIsolation> implicitAsyncIsolation);
15881588

15891589
RValue emitApplyOfDefaultArgGenerator(SILLocation loc,
15901590
ConcreteDeclRef defaultArgsOwner,

lib/SILGen/SILGenProlog.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,9 @@ void SILGenFunction::emitPreconditionCheckExpectedExecutor(
660660
if (!checkExecutor)
661661
return;
662662

663+
// We don't want the debugger to step into these.
664+
loc.markAutoGenerated();
665+
663666
// Get the executor.
664667
SILValue executor = B.createExtractExecutor(loc, executorOrActor);
665668

lib/Sema/ConstraintSystem.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,16 @@ unwrapPropertyWrapperParameterTypes(ConstraintSystem &cs, AbstractFunctionDecl *
12331233
functionType->getExtInfo());
12341234
}
12351235

1236+
/// Determine whether the given locator is for a witness or requirement.
1237+
static bool isRequirementOrWitness(const ConstraintLocatorBuilder &locator) {
1238+
if (auto last = locator.last()) {
1239+
return last->getKind() == ConstraintLocator::ProtocolRequirement ||
1240+
last->getKind() == ConstraintLocator::Witness;
1241+
}
1242+
1243+
return false;
1244+
}
1245+
12361246
std::pair<Type, Type>
12371247
ConstraintSystem::getTypeOfReference(ValueDecl *value,
12381248
FunctionRefKind functionRefKind,
@@ -1245,9 +1255,12 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
12451255

12461256
OpenedTypeMap replacements;
12471257

1248-
auto openedType =
1249-
openFunctionType(func->getInterfaceType()->castTo<AnyFunctionType>(),
1250-
locator, replacements, func->getDeclContext());
1258+
AnyFunctionType *funcType = func->getInterfaceType()
1259+
->castTo<AnyFunctionType>();
1260+
if (!isRequirementOrWitness(locator))
1261+
funcType = applyGlobalActorType(funcType, func, useDC);
1262+
auto openedType = openFunctionType(
1263+
funcType, locator, replacements, func->getDeclContext());
12511264

12521265
// If we opened up any type variables, record the replacements.
12531266
recordOpenedTypes(locator, replacements);
@@ -1274,10 +1287,12 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
12741287
auto numLabelsToRemove = getNumRemovedArgumentLabels(
12751288
funcDecl, /*isCurriedInstanceReference=*/false, functionRefKind);
12761289

1290+
if (!isRequirementOrWitness(locator))
1291+
funcType = applyGlobalActorType(funcType, funcDecl, useDC);
1292+
12771293
auto openedType = openFunctionType(funcType, locator, replacements,
12781294
funcDecl->getDeclContext())
12791295
->removeArgumentLabels(numLabelsToRemove);
1280-
12811296
openedType = unwrapPropertyWrapperParameterTypes(*this, funcDecl, functionRefKind,
12821297
openedType->getAs<FunctionType>(),
12831298
locator);
@@ -1514,16 +1529,6 @@ static void addSelfConstraint(ConstraintSystem &cs, Type objectTy, Type selfTy,
15141529
cs.getConstraintLocator(locator));
15151530
}
15161531

1517-
/// Determine whether the given locator is for a witness or requirement.
1518-
static bool isRequirementOrWitness(const ConstraintLocatorBuilder &locator) {
1519-
if (auto last = locator.last()) {
1520-
return last->getKind() == ConstraintLocator::ProtocolRequirement ||
1521-
last->getKind() == ConstraintLocator::Witness;
1522-
}
1523-
1524-
return false;
1525-
}
1526-
15271532
Type constraints::getDynamicSelfReplacementType(
15281533
Type baseObjTy, const ValueDecl *member, ConstraintLocator *memberLocator) {
15291534
// Constructions must always have their dynamic 'Self' result type replaced
@@ -1623,6 +1628,9 @@ ConstraintSystem::getTypeOfMemberReference(
16231628
isa<EnumElementDecl>(value)) {
16241629
// This is the easy case.
16251630
funcType = value->getInterfaceType()->castTo<AnyFunctionType>();
1631+
1632+
if (!isRequirementOrWitness(locator))
1633+
funcType = applyGlobalActorType(funcType, value, useDC);
16261634
} else {
16271635
// For a property, build a type (Self) -> PropType.
16281636
// For a subscript, build a type (Self) -> (Indices...) -> ElementType.

0 commit comments

Comments
 (0)