@@ -4753,6 +4753,24 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
4753
4753
return std::nullopt;
4754
4754
}
4755
4755
4756
+ // If the declaration is explicitly marked with 'execution', return the
4757
+ // appropriate isolation.
4758
+ //
4759
+ // NOTE: This needs to occur before we handle an explicit nonisolated attr,
4760
+ // since if @execution and nonisolated are used together, we want to ensure
4761
+ // that @execution takes priority. This ensures that if we import code from a
4762
+ // module that was compiled with a different value for
4763
+ // NonIsolatedAsyncInheritsIsolationFromContext, we get the semantics of the
4764
+ // source module.
4765
+ if (concurrentExecutionAttr) {
4766
+ switch (concurrentExecutionAttr->getBehavior ()) {
4767
+ case ExecutionKind::Concurrent:
4768
+ return ActorIsolation::forNonisolated (false /* is unsafe*/ );
4769
+ case ExecutionKind::Caller:
4770
+ return ActorIsolation::forCallerIsolationInheriting ();
4771
+ }
4772
+ }
4773
+
4756
4774
// If the declaration is explicitly marked 'nonisolated', report it as
4757
4775
// independent.
4758
4776
if (nonisolatedAttr) {
@@ -4857,17 +4875,6 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
4857
4875
.withPreconcurrency (decl->preconcurrency () || isUnsafe);
4858
4876
}
4859
4877
4860
- // If the declaration is explicitly marked with 'execution', return the
4861
- // appropriate isolation.
4862
- if (concurrentExecutionAttr) {
4863
- switch (concurrentExecutionAttr->getBehavior ()) {
4864
- case ExecutionKind::Concurrent:
4865
- return ActorIsolation::forNonisolated (false /* is unsafe*/ );
4866
- case ExecutionKind::Caller:
4867
- return ActorIsolation::forCallerIsolationInheriting ();
4868
- }
4869
- }
4870
-
4871
4878
llvm_unreachable (" Forgot about an attribute?" );
4872
4879
}
4873
4880
@@ -5534,6 +5541,9 @@ static void addAttributesForActorIsolation(ValueDecl *value,
5534
5541
ASTContext &ctx = value->getASTContext ();
5535
5542
switch (isolation) {
5536
5543
case ActorIsolation::CallerIsolationInheriting:
5544
+ value->getAttrs ().add (new (ctx) ExecutionAttr (ExecutionKind::Caller,
5545
+ /* implicit=*/ true ));
5546
+ break ;
5537
5547
case ActorIsolation::Nonisolated:
5538
5548
case ActorIsolation::NonisolatedUnsafe: {
5539
5549
value->getAttrs ().add (new (ctx) NonisolatedAttr (
@@ -5568,6 +5578,83 @@ static void addAttributesForActorIsolation(ValueDecl *value,
5568
5578
}
5569
5579
}
5570
5580
5581
+ // / Determine the default isolation and isolation source for this declaration,
5582
+ // / which may still be overridden by other inference rules.
5583
+ static std::tuple<InferredActorIsolation, ValueDecl *,
5584
+ std::optional<ActorIsolation>>
5585
+ computeDefaultInferredActorIsolation (ValueDecl *value) {
5586
+ auto &ctx = value->getASTContext ();
5587
+
5588
+ // If we are supposed to infer main actor isolation by default for entities
5589
+ // within our module, make our default isolation main actor.
5590
+ if (ctx.LangOpts .hasFeature (Feature::UnspecifiedMeansMainActorIsolated) &&
5591
+ value->getModuleContext () == ctx.MainModule ) {
5592
+
5593
+ // Default global actor isolation does not apply to any declarations
5594
+ // within actors and distributed actors.
5595
+ bool inActorContext = false ;
5596
+ auto *dc = value->getInnermostDeclContext ();
5597
+ while (dc && !inActorContext) {
5598
+ if (auto *nominal = dc->getSelfNominalTypeDecl ()) {
5599
+ inActorContext = nominal->isAnyActor ();
5600
+ }
5601
+ dc = dc->getParent ();
5602
+ }
5603
+
5604
+ if (!inActorContext) {
5605
+ // FIXME: deinit should be implicitly MainActor too.
5606
+ if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
5607
+ isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
5608
+ isa<ConstructorDecl>(value)) {
5609
+ return {{ActorIsolation::forMainActor (ctx), {}}, nullptr , {}};
5610
+ }
5611
+ }
5612
+ }
5613
+
5614
+ // If we have an async function... by default we inherit isolation.
5615
+ if (ctx.LangOpts .hasFeature (
5616
+ Feature::NonIsolatedAsyncInheritsIsolationFromContext)) {
5617
+ if (auto *func = dyn_cast<AbstractFunctionDecl>(value);
5618
+ func && func->hasAsync () &&
5619
+ func->getModuleContext () == ctx.MainModule ) {
5620
+ return {
5621
+ {ActorIsolation::forCallerIsolationInheriting (), {}}, nullptr , {}};
5622
+ }
5623
+ }
5624
+
5625
+ if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
5626
+ // A @Sendable function is assumed to be actor-independent.
5627
+ if (func->isSendable ()) {
5628
+ return {
5629
+ {ActorIsolation::forNonisolated (/* unsafe=*/ false ), {}}, nullptr , {}};
5630
+ }
5631
+ }
5632
+
5633
+ // When no other isolation applies, an actor's non-async init is independent
5634
+ if (auto nominal = value->getDeclContext ()->getSelfNominalTypeDecl ())
5635
+ if (nominal->isAnyActor ())
5636
+ if (auto ctor = dyn_cast<ConstructorDecl>(value))
5637
+ if (!ctor->hasAsync ())
5638
+ return {{ActorIsolation::forNonisolated (/* unsafe=*/ false ), {}},
5639
+ nullptr ,
5640
+ {}};
5641
+
5642
+ // Look for and remember the overridden declaration's isolation.
5643
+ if (auto *overriddenValue = value->getOverriddenDeclOrSuperDeinit ()) {
5644
+ // Use the overridden decl's isolation as the default isolation for this
5645
+ // decl.
5646
+ auto isolation = getOverriddenIsolationFor (value);
5647
+ return {{isolation,
5648
+ IsolationSource (overriddenValue, IsolationSource::Override)},
5649
+ overriddenValue,
5650
+ isolation}; // use the overridden decl's iso as the default
5651
+ // isolation for this decl.
5652
+ }
5653
+
5654
+ // We did not find anything special, return unspecified.
5655
+ return {{ActorIsolation::forUnspecified (), {}}, nullptr , {}};
5656
+ }
5657
+
5571
5658
InferredActorIsolation ActorIsolationRequest::evaluate (
5572
5659
Evaluator &evaluator, ValueDecl *value) const {
5573
5660
// If this declaration has actor-isolated "self", it's isolated to that
@@ -5611,7 +5698,20 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
5611
5698
value->getAttrs ().add (preconcurrency);
5612
5699
}
5613
5700
5614
- if (FuncDecl *fd = dyn_cast<FuncDecl>(value)) {
5701
+ // Check if we inferred CallerIsolationInheriting from our isolation attr, but
5702
+ // did not have an ExecutionKind::Caller attached to it.
5703
+ //
5704
+ // DISCUSSION: This occurs when we have a value decl that is explicitly marked
5705
+ // as nonisolated but since NonIsolatedAsyncInheritsIsolationFromContext is
5706
+ // enabled, we return CallerIsolationInheriting.
5707
+ if (isolationFromAttr && isolationFromAttr->getKind () ==
5708
+ ActorIsolation::CallerIsolationInheriting &&
5709
+ !value->getAttrs ().hasAttribute <ExecutionAttr>()) {
5710
+ value->getAttrs ().add (new (ctx) ExecutionAttr (ExecutionKind::Caller,
5711
+ /* implicit=*/ true ));
5712
+ }
5713
+
5714
+ if (auto *fd = dyn_cast<FuncDecl>(value)) {
5615
5715
// Main.main() and Main.$main are implicitly MainActor-protected.
5616
5716
// Any other isolation is an error.
5617
5717
std::optional<ActorIsolation> mainIsolation =
@@ -5644,74 +5744,11 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
5644
5744
IsolationSource (/* source*/ nullptr , IsolationSource::Explicit)};
5645
5745
}
5646
5746
5647
- // Determine the default isolation for this declaration, which may still be
5648
- // overridden by other inference rules.
5649
- ActorIsolation defaultIsolation = ActorIsolation::forUnspecified ();
5650
- IsolationSource defaultIsolationSource;
5651
-
5652
- // If we are supposed to infer main actor isolation by default for entities
5653
- // within our module, make our default isolation main actor.
5654
- if (ctx.LangOpts .hasFeature (Feature::UnspecifiedMeansMainActorIsolated) &&
5655
- value->getModuleContext () == ctx.MainModule ) {
5656
-
5657
- // Default global actor isolation does not apply to any declarations
5658
- // within actors and distributed actors.
5659
- bool inActorContext = false ;
5660
- auto *dc = value->getInnermostDeclContext ();
5661
- while (dc && !inActorContext) {
5662
- if (auto *nominal = dc->getSelfNominalTypeDecl ()) {
5663
- inActorContext = nominal->isAnyActor ();
5664
- }
5665
- dc = dc->getParent ();
5666
- }
5667
-
5668
- if (!inActorContext) {
5669
- // FIXME: deinit should be implicitly MainActor too.
5670
- if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
5671
- isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
5672
- isa<ConstructorDecl>(value)) {
5673
- defaultIsolation = ActorIsolation::forMainActor (ctx);
5674
- }
5675
- }
5676
- }
5677
-
5678
- // If we have an async function... by default we inherit isolation.
5679
- if (ctx.LangOpts .hasFeature (
5680
- Feature::NonIsolatedAsyncInheritsIsolationFromContext)) {
5681
- if (auto *func = dyn_cast<AbstractFunctionDecl>(value);
5682
- func && func->hasAsync () &&
5683
- func->getModuleContext () == ctx.MainModule ) {
5684
- defaultIsolation = ActorIsolation::forCallerIsolationInheriting ();
5685
- }
5686
- }
5687
-
5688
- if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
5689
- // A @Sendable function is assumed to be actor-independent.
5690
- if (func->isSendable ()) {
5691
- defaultIsolation = ActorIsolation::forNonisolated (/* unsafe=*/ false );
5692
- }
5693
- }
5694
-
5695
- // When no other isolation applies, an actor's non-async init is independent
5696
- if (auto nominal = value->getDeclContext ()->getSelfNominalTypeDecl ())
5697
- if (nominal->isAnyActor ())
5698
- if (auto ctor = dyn_cast<ConstructorDecl>(value))
5699
- if (!ctor->hasAsync ())
5700
- defaultIsolation = ActorIsolation::forNonisolated (/* unsafe=*/ false );
5701
-
5702
- // Look for and remember the overridden declaration's isolation.
5703
- std::optional<ActorIsolation> overriddenIso;
5704
- ValueDecl *overriddenValue = value->getOverriddenDeclOrSuperDeinit ();
5705
- if (overriddenValue) {
5706
- // use the overridden decl's iso as the default isolation for this decl.
5707
- defaultIsolation = getOverriddenIsolationFor (value);
5708
- defaultIsolationSource =
5709
- IsolationSource (overriddenValue, IsolationSource::Override);
5710
- overriddenIso = defaultIsolation;
5711
- }
5712
-
5713
- // NOTE: After this point, the default has been set. Only touch the default
5714
- // isolation above this point since code below assumes it is now constant.
5747
+ InferredActorIsolation defaultIsolation;
5748
+ ValueDecl *overriddenValue;
5749
+ std::optional<ActorIsolation> overridenIsolation;
5750
+ std::tie (defaultIsolation, overriddenValue, overridenIsolation) =
5751
+ computeDefaultInferredActorIsolation (value);
5715
5752
5716
5753
// Function used when returning an inferred isolation.
5717
5754
auto inferredIsolation = [&](ActorIsolation inferred,
@@ -5722,16 +5759,17 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
5722
5759
// if the inferred isolation is not valid, then carry-over the overridden
5723
5760
// declaration's isolation as this decl's inferred isolation.
5724
5761
switch (validOverrideIsolation (value, inferred, overriddenValue,
5725
- *overriddenIso )) {
5762
+ *overridenIsolation )) {
5726
5763
case OverrideIsolationResult::Allowed:
5727
5764
case OverrideIsolationResult::Sendable:
5728
5765
break ;
5729
5766
5730
5767
case OverrideIsolationResult::Disallowed:
5731
- if (overriddenValue->hasClangNode () && overriddenIso->isUnspecified ()) {
5732
- inferred = overriddenIso->withPreconcurrency (true );
5768
+ if (overriddenValue->hasClangNode () &&
5769
+ overridenIsolation->isUnspecified ()) {
5770
+ inferred = overridenIsolation->withPreconcurrency (true );
5733
5771
} else {
5734
- inferred = *overriddenIso ;
5772
+ inferred = *overridenIsolation ;
5735
5773
}
5736
5774
break ;
5737
5775
}
@@ -5758,6 +5796,7 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
5758
5796
addAttributesForActorIsolation (value, inferred);
5759
5797
break ;
5760
5798
case ActorIsolation::CallerIsolationInheriting:
5799
+ addAttributesForActorIsolation (value, inferred);
5761
5800
break ;
5762
5801
case ActorIsolation::Erased:
5763
5802
llvm_unreachable (" cannot infer erased isolation" );
@@ -5988,8 +6027,18 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
5988
6027
}
5989
6028
}
5990
6029
5991
- // Default isolation for this member.
5992
- return {defaultIsolation, defaultIsolationSource};
6030
+ // We did not invoke any earlier rules... so just return the default
6031
+ // isolation.
6032
+ if (defaultIsolation.isolation .getKind () ==
6033
+ ActorIsolation::CallerIsolationInheriting) {
6034
+ // If we have caller isolation inheriting, attach the attribute for it so
6035
+ // that we preserve that we chose CallerIsolationInheriting through
6036
+ // serialization. We do this since we need to support compiling where
6037
+ // nonisolated is the default and where caller isolation inheriting is the
6038
+ // default.
6039
+ addAttributesForActorIsolation (value, defaultIsolation.isolation );
6040
+ }
6041
+ return defaultIsolation;
5993
6042
}
5994
6043
5995
6044
bool HasIsolatedSelfRequest::evaluate (
0 commit comments