@@ -3143,7 +3143,10 @@ namespace {
3143
3143
if (!unsatisfiedIsolation)
3144
3144
return false ;
3145
3145
3146
- if (refineRequiredIsolation (*unsatisfiedIsolation))
3146
+ bool onlyArgsCrossIsolation = callOptions.contains (
3147
+ ActorReferenceResult::Flags::OnlyArgsCrossIsolation);
3148
+ if (!onlyArgsCrossIsolation &&
3149
+ refineRequiredIsolation (*unsatisfiedIsolation))
3147
3150
return false ;
3148
3151
3149
3152
// At this point, we know a jump is made to the callee that yields
@@ -4757,6 +4760,7 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
4757
4760
4758
4761
Initializer *dc = nullptr ;
4759
4762
Expr *initExpr = nullptr ;
4763
+ ActorIsolation enclosingIsolation;
4760
4764
4761
4765
if (auto *pbd = var->getParentPatternBinding ()) {
4762
4766
if (!var->isParentInitialized ())
@@ -4765,6 +4769,7 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
4765
4769
auto i = pbd->getPatternEntryIndexForVarDecl (var);
4766
4770
dc = cast<Initializer>(pbd->getInitContext (i));
4767
4771
initExpr = var->getParentInitializer ();
4772
+ enclosingIsolation = getActorIsolation (var);
4768
4773
} else if (auto *param = dyn_cast<ParamDecl>(var)) {
4769
4774
// If this parameter corresponds to a stored property for a
4770
4775
// memberwise initializer, the default argument is the default
@@ -4782,13 +4787,27 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
4782
4787
4783
4788
dc = param->getDefaultArgumentInitContext ();
4784
4789
initExpr = param->getTypeCheckedDefaultExpr ();
4790
+ enclosingIsolation =
4791
+ getActorIsolationOfContext (param->getDeclContext ());
4785
4792
}
4786
4793
4787
4794
if (!dc || !initExpr)
4788
4795
return ActorIsolation::forUnspecified ();
4789
4796
4797
+ // If the default argument has isolation, it must match the
4798
+ // isolation of the decl context.
4790
4799
ActorIsolationChecker checker (dc);
4791
- return checker.computeRequiredIsolation (initExpr);
4800
+ auto requiredIsolation = checker.computeRequiredIsolation (initExpr);
4801
+ if (requiredIsolation.isActorIsolated ()) {
4802
+ if (enclosingIsolation != requiredIsolation) {
4803
+ var->diagnose (
4804
+ diag::isolated_default_argument_context,
4805
+ requiredIsolation, enclosingIsolation);
4806
+ return ActorIsolation::forUnspecified ();
4807
+ }
4808
+ }
4809
+
4810
+ return requiredIsolation;
4792
4811
}
4793
4812
4794
4813
void swift::checkOverrideActorIsolation (ValueDecl *value) {
@@ -5859,8 +5878,8 @@ bool swift::isAccessibleAcrossActors(
5859
5878
}
5860
5879
5861
5880
ActorReferenceResult ActorReferenceResult::forSameConcurrencyDomain (
5862
- ActorIsolation isolation) {
5863
- return ActorReferenceResult{SameConcurrencyDomain, llvm::None , isolation};
5881
+ ActorIsolation isolation, Options options ) {
5882
+ return ActorReferenceResult{SameConcurrencyDomain, options , isolation};
5864
5883
}
5865
5884
5866
5885
ActorReferenceResult ActorReferenceResult::forEntersActor (
@@ -5869,8 +5888,8 @@ ActorReferenceResult ActorReferenceResult::forEntersActor(
5869
5888
}
5870
5889
5871
5890
ActorReferenceResult ActorReferenceResult::forExitsActorToNonisolated (
5872
- ActorIsolation isolation) {
5873
- return ActorReferenceResult{ExitsActorToNonisolated, llvm::None , isolation};
5891
+ ActorIsolation isolation, Options options ) {
5892
+ return ActorReferenceResult{ExitsActorToNonisolated, options , isolation};
5874
5893
}
5875
5894
5876
5895
// Determine if two actor isolation contexts are considered to be equivalent.
@@ -5906,10 +5925,24 @@ ActorReferenceResult ActorReferenceResult::forReference(
5906
5925
declIsolation = declIsolation.subst (declRef.getSubstitutions ());
5907
5926
}
5908
5927
5928
+ // Determine what adjustments we need to perform for cross-actor
5929
+ // references.
5930
+ Options options = llvm::None;
5931
+
5932
+ // FIXME: Actor constructors are modeled as isolated to the actor
5933
+ // so that Sendable checking is applied to their arguments, but the
5934
+ // call itself does not hop to another executor.
5935
+ if (auto ctor = dyn_cast<ConstructorDecl>(declRef.getDecl ())) {
5936
+ if (auto nominal = ctor->getDeclContext ()->getSelfNominalTypeDecl ()) {
5937
+ if (nominal->isAnyActor ())
5938
+ options |= Flags::OnlyArgsCrossIsolation;
5939
+ }
5940
+ }
5941
+
5909
5942
// If the entity we are referencing is not a value, we're in the same
5910
5943
// concurrency domain.
5911
5944
if (isNonValueReference (declRef.getDecl ()))
5912
- return forSameConcurrencyDomain (declIsolation);
5945
+ return forSameConcurrencyDomain (declIsolation, options );
5913
5946
5914
5947
// Compute the isolation of the context, if not provided.
5915
5948
ActorIsolation contextIsolation = ActorIsolation::forUnspecified ();
@@ -5928,11 +5961,11 @@ ActorReferenceResult ActorReferenceResult::forReference(
5928
5961
if (isAsyncDecl (declRef) && contextIsolation.isActorIsolated () &&
5929
5962
!declRef.getDecl ()->getAttrs ()
5930
5963
.hasAttribute <UnsafeInheritExecutorAttr>())
5931
- return forExitsActorToNonisolated (contextIsolation);
5964
+ return forExitsActorToNonisolated (contextIsolation, options );
5932
5965
5933
5966
// Otherwise, we stay in the same concurrency domain, whether on an actor
5934
5967
// or in a task.
5935
- return forSameConcurrencyDomain (declIsolation);
5968
+ return forSameConcurrencyDomain (declIsolation, options );
5936
5969
}
5937
5970
5938
5971
// The declaration we are accessing is actor-isolated. First, check whether
@@ -5941,11 +5974,11 @@ ActorReferenceResult ActorReferenceResult::forReference(
5941
5974
declIsolation.getActorInstanceParameter () == 0 ) {
5942
5975
// If this instance is isolated, we're in the same concurrency domain.
5943
5976
if (actorInstance->isIsolated ())
5944
- return forSameConcurrencyDomain (declIsolation);
5977
+ return forSameConcurrencyDomain (declIsolation, options );
5945
5978
} else if (equivalentIsolationContexts (declIsolation, contextIsolation)) {
5946
5979
// The context isolation matches, so we are in the same concurrency
5947
5980
// domain.
5948
- return forSameConcurrencyDomain (declIsolation);
5981
+ return forSameConcurrencyDomain (declIsolation, options );
5949
5982
}
5950
5983
5951
5984
// Initializing an actor isolated stored property with a value effectively
@@ -5965,7 +5998,8 @@ ActorReferenceResult ActorReferenceResult::forReference(
5965
5998
// Treat the decl isolation as 'preconcurrency' to downgrade violations
5966
5999
// to warnings, because violating Sendable here is accepted by the
5967
6000
// Swift 5.9 compiler.
5968
- return forEntersActor (declIsolation, Flags::Preconcurrency);
6001
+ options |= Flags::Preconcurrency;
6002
+ return forEntersActor (declIsolation, options);
5969
6003
}
5970
6004
}
5971
6005
}
@@ -5975,7 +6009,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
5975
6009
if (actorInstance &&
5976
6010
checkedByFlowIsolation (
5977
6011
fromDC, *actorInstance, declRef.getDecl (), declRefLoc, useKind))
5978
- return forSameConcurrencyDomain (declIsolation);
6012
+ return forSameConcurrencyDomain (declIsolation, options );
5979
6013
5980
6014
// If we are delegating to another initializer, treat them as being in the
5981
6015
// same concurrency domain.
@@ -5984,7 +6018,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
5984
6018
if (actorInstance && actorInstance->isSelf () &&
5985
6019
isa<ConstructorDecl>(declRef.getDecl ()) &&
5986
6020
isa<ConstructorDecl>(fromDC))
5987
- return forSameConcurrencyDomain (declIsolation);
6021
+ return forSameConcurrencyDomain (declIsolation, options );
5988
6022
5989
6023
// If there is an instance that corresponds to 'self',
5990
6024
// we are in a constructor or destructor, and we have a stored property of
@@ -5994,18 +6028,14 @@ ActorReferenceResult ActorReferenceResult::forReference(
5994
6028
isNonInheritedStorage (declRef.getDecl (), fromDC) &&
5995
6029
declIsolation.isGlobalActor () &&
5996
6030
(isa<ConstructorDecl>(fromDC) || isa<DestructorDecl>(fromDC)))
5997
- return forSameConcurrencyDomain (declIsolation);
5998
-
5999
- // Determine what adjustments we need to perform for cross-actor
6000
- // references.
6001
- Options options = llvm::None;
6031
+ return forSameConcurrencyDomain (declIsolation, options);
6002
6032
6003
6033
// At this point, we are accessing the target from outside the actor.
6004
6034
// First, check whether it is something that can be accessed directly,
6005
6035
// without any kind of promotion.
6006
6036
if (isAccessibleAcrossActors (
6007
6037
declRef.getDecl (), declIsolation, fromDC, options, actorInstance))
6008
- return forEntersActor (declIsolation, llvm::None );
6038
+ return forEntersActor (declIsolation, options );
6009
6039
6010
6040
// This is a cross-actor reference.
6011
6041
0 commit comments