@@ -3188,7 +3188,10 @@ namespace {
3188
3188
if (!unsatisfiedIsolation)
3189
3189
return false ;
3190
3190
3191
- if (refineRequiredIsolation (*unsatisfiedIsolation))
3191
+ bool onlyArgsCrossIsolation = callOptions.contains (
3192
+ ActorReferenceResult::Flags::OnlyArgsCrossIsolation);
3193
+ if (!onlyArgsCrossIsolation &&
3194
+ refineRequiredIsolation (*unsatisfiedIsolation))
3192
3195
return false ;
3193
3196
3194
3197
// At this point, we know a jump is made to the callee that yields
@@ -4808,6 +4811,7 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
4808
4811
4809
4812
Initializer *dc = nullptr ;
4810
4813
Expr *initExpr = nullptr ;
4814
+ ActorIsolation enclosingIsolation;
4811
4815
4812
4816
if (auto *pbd = var->getParentPatternBinding ()) {
4813
4817
if (!var->isParentInitialized ())
@@ -4816,6 +4820,7 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
4816
4820
auto i = pbd->getPatternEntryIndexForVarDecl (var);
4817
4821
dc = cast<Initializer>(pbd->getInitContext (i));
4818
4822
initExpr = var->getParentInitializer ();
4823
+ enclosingIsolation = getActorIsolation (var);
4819
4824
} else if (auto *param = dyn_cast<ParamDecl>(var)) {
4820
4825
// If this parameter corresponds to a stored property for a
4821
4826
// memberwise initializer, the default argument is the default
@@ -4833,13 +4838,27 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
4833
4838
4834
4839
dc = param->getDefaultArgumentInitContext ();
4835
4840
initExpr = param->getTypeCheckedDefaultExpr ();
4841
+ enclosingIsolation =
4842
+ getActorIsolationOfContext (param->getDeclContext ());
4836
4843
}
4837
4844
4838
4845
if (!dc || !initExpr)
4839
4846
return ActorIsolation::forUnspecified ();
4840
4847
4848
+ // If the default argument has isolation, it must match the
4849
+ // isolation of the decl context.
4841
4850
ActorIsolationChecker checker (dc);
4842
- return checker.computeRequiredIsolation (initExpr);
4851
+ auto requiredIsolation = checker.computeRequiredIsolation (initExpr);
4852
+ if (requiredIsolation.isActorIsolated ()) {
4853
+ if (enclosingIsolation != requiredIsolation) {
4854
+ var->diagnose (
4855
+ diag::isolated_default_argument_context,
4856
+ requiredIsolation, enclosingIsolation);
4857
+ return ActorIsolation::forUnspecified ();
4858
+ }
4859
+ }
4860
+
4861
+ return requiredIsolation;
4843
4862
}
4844
4863
4845
4864
void swift::checkOverrideActorIsolation (ValueDecl *value) {
@@ -5955,8 +5974,8 @@ bool swift::isAccessibleAcrossActors(
5955
5974
}
5956
5975
5957
5976
ActorReferenceResult ActorReferenceResult::forSameConcurrencyDomain (
5958
- ActorIsolation isolation) {
5959
- return ActorReferenceResult{SameConcurrencyDomain, llvm::None , isolation};
5977
+ ActorIsolation isolation, Options options ) {
5978
+ return ActorReferenceResult{SameConcurrencyDomain, options , isolation};
5960
5979
}
5961
5980
5962
5981
ActorReferenceResult ActorReferenceResult::forEntersActor (
@@ -5965,8 +5984,8 @@ ActorReferenceResult ActorReferenceResult::forEntersActor(
5965
5984
}
5966
5985
5967
5986
ActorReferenceResult ActorReferenceResult::forExitsActorToNonisolated (
5968
- ActorIsolation isolation) {
5969
- return ActorReferenceResult{ExitsActorToNonisolated, llvm::None , isolation};
5987
+ ActorIsolation isolation, Options options ) {
5988
+ return ActorReferenceResult{ExitsActorToNonisolated, options , isolation};
5970
5989
}
5971
5990
5972
5991
// Determine if two actor isolation contexts are considered to be equivalent.
@@ -6002,10 +6021,24 @@ ActorReferenceResult ActorReferenceResult::forReference(
6002
6021
declIsolation = declIsolation.subst (declRef.getSubstitutions ());
6003
6022
}
6004
6023
6024
+ // Determine what adjustments we need to perform for cross-actor
6025
+ // references.
6026
+ Options options = llvm::None;
6027
+
6028
+ // FIXME: Actor constructors are modeled as isolated to the actor
6029
+ // so that Sendable checking is applied to their arguments, but the
6030
+ // call itself does not hop to another executor.
6031
+ if (auto ctor = dyn_cast<ConstructorDecl>(declRef.getDecl ())) {
6032
+ if (auto nominal = ctor->getDeclContext ()->getSelfNominalTypeDecl ()) {
6033
+ if (nominal->isAnyActor ())
6034
+ options |= Flags::OnlyArgsCrossIsolation;
6035
+ }
6036
+ }
6037
+
6005
6038
// If the entity we are referencing is not a value, we're in the same
6006
6039
// concurrency domain.
6007
6040
if (isNonValueReference (declRef.getDecl ()))
6008
- return forSameConcurrencyDomain (declIsolation);
6041
+ return forSameConcurrencyDomain (declIsolation, options );
6009
6042
6010
6043
// Compute the isolation of the context, if not provided.
6011
6044
ActorIsolation contextIsolation = ActorIsolation::forUnspecified ();
@@ -6024,11 +6057,11 @@ ActorReferenceResult ActorReferenceResult::forReference(
6024
6057
if (isAsyncDecl (declRef) && contextIsolation.isActorIsolated () &&
6025
6058
!declRef.getDecl ()->getAttrs ()
6026
6059
.hasAttribute <UnsafeInheritExecutorAttr>())
6027
- return forExitsActorToNonisolated (contextIsolation);
6060
+ return forExitsActorToNonisolated (contextIsolation, options );
6028
6061
6029
6062
// Otherwise, we stay in the same concurrency domain, whether on an actor
6030
6063
// or in a task.
6031
- return forSameConcurrencyDomain (declIsolation);
6064
+ return forSameConcurrencyDomain (declIsolation, options );
6032
6065
}
6033
6066
6034
6067
// The declaration we are accessing is actor-isolated. First, check whether
@@ -6037,11 +6070,11 @@ ActorReferenceResult ActorReferenceResult::forReference(
6037
6070
declIsolation.getActorInstanceParameter () == 0 ) {
6038
6071
// If this instance is isolated, we're in the same concurrency domain.
6039
6072
if (actorInstance->isIsolated ())
6040
- return forSameConcurrencyDomain (declIsolation);
6073
+ return forSameConcurrencyDomain (declIsolation, options );
6041
6074
} else if (equivalentIsolationContexts (declIsolation, contextIsolation)) {
6042
6075
// The context isolation matches, so we are in the same concurrency
6043
6076
// domain.
6044
- return forSameConcurrencyDomain (declIsolation);
6077
+ return forSameConcurrencyDomain (declIsolation, options );
6045
6078
}
6046
6079
6047
6080
// Initializing an actor isolated stored property with a value effectively
@@ -6061,7 +6094,8 @@ ActorReferenceResult ActorReferenceResult::forReference(
6061
6094
// Treat the decl isolation as 'preconcurrency' to downgrade violations
6062
6095
// to warnings, because violating Sendable here is accepted by the
6063
6096
// Swift 5.9 compiler.
6064
- return forEntersActor (declIsolation, Flags::Preconcurrency);
6097
+ options |= Flags::Preconcurrency;
6098
+ return forEntersActor (declIsolation, options);
6065
6099
}
6066
6100
}
6067
6101
}
@@ -6071,7 +6105,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
6071
6105
if (actorInstance &&
6072
6106
checkedByFlowIsolation (
6073
6107
fromDC, *actorInstance, declRef.getDecl (), declRefLoc, useKind))
6074
- return forSameConcurrencyDomain (declIsolation);
6108
+ return forSameConcurrencyDomain (declIsolation, options );
6075
6109
6076
6110
// If we are delegating to another initializer, treat them as being in the
6077
6111
// same concurrency domain.
@@ -6080,7 +6114,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
6080
6114
if (actorInstance && actorInstance->isSelf () &&
6081
6115
isa<ConstructorDecl>(declRef.getDecl ()) &&
6082
6116
isa<ConstructorDecl>(fromDC))
6083
- return forSameConcurrencyDomain (declIsolation);
6117
+ return forSameConcurrencyDomain (declIsolation, options );
6084
6118
6085
6119
// If there is an instance that corresponds to 'self',
6086
6120
// we are in a constructor or destructor, and we have a stored property of
@@ -6090,18 +6124,14 @@ ActorReferenceResult ActorReferenceResult::forReference(
6090
6124
isNonInheritedStorage (declRef.getDecl (), fromDC) &&
6091
6125
declIsolation.isGlobalActor () &&
6092
6126
(isa<ConstructorDecl>(fromDC) || isa<DestructorDecl>(fromDC)))
6093
- return forSameConcurrencyDomain (declIsolation);
6094
-
6095
- // Determine what adjustments we need to perform for cross-actor
6096
- // references.
6097
- Options options = llvm::None;
6127
+ return forSameConcurrencyDomain (declIsolation, options);
6098
6128
6099
6129
// At this point, we are accessing the target from outside the actor.
6100
6130
// First, check whether it is something that can be accessed directly,
6101
6131
// without any kind of promotion.
6102
6132
if (isAccessibleAcrossActors (
6103
6133
declRef.getDecl (), declIsolation, fromDC, options, actorInstance))
6104
- return forEntersActor (declIsolation, llvm::None );
6134
+ return forEntersActor (declIsolation, options );
6105
6135
6106
6136
// This is a cross-actor reference.
6107
6137
0 commit comments