Skip to content

Commit ec2aace

Browse files
committed
[Concurrency] Fix actor-isolation override checking with @asyncHandler.
`@asyncHandler` methods can override with a completely different actor isolation because they will hop to the appropriate actor themselves. Therefore, allow differing actor isolation when an `@asyncHandler` method overrides another method, and don't propagate the actor isolation from the overridden method to the overriding `@asyncHandler` method.
1 parent 8b9cbe2 commit ec2aace

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,6 +1752,16 @@ static Optional<ActorIsolation> getIsolationFromWitnessedRequirements(
17521752
return std::get<1>(isolatedRequirements.front());
17531753
}
17541754

1755+
// Check whether a declaration is an asynchronous handler.
1756+
static bool isAsyncHandler(ValueDecl *value) {
1757+
if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
1758+
if (func->isAsyncHandler())
1759+
return true;
1760+
}
1761+
1762+
return false;
1763+
}
1764+
17551765
ActorIsolation ActorIsolationRequest::evaluate(
17561766
Evaluator &evaluator, ValueDecl *value) const {
17571767
// If this declaration has one of the actor isolation attributes, report
@@ -1807,15 +1817,19 @@ ActorIsolation ActorIsolationRequest::evaluate(
18071817
// If the declaration overrides another declaration, it must have the same
18081818
// actor isolation.
18091819
if (auto overriddenValue = value->getOverriddenDecl()) {
1810-
auto isolation = getActorIsolation(overriddenValue);
1811-
SubstitutionMap subs;
1812-
if (auto env = value->getInnermostDeclContext()
1813-
->getGenericEnvironmentOfContext()) {
1814-
subs = SubstitutionMap::getOverrideSubstitutions(
1815-
overriddenValue, value, subs);
1816-
}
1820+
// Ignore the overridden declaration's isolation for an async handler,
1821+
// because async handlers dispatch to wherever they need to be.
1822+
if (!isAsyncHandler(value)) {
1823+
auto isolation = getActorIsolation(overriddenValue);
1824+
SubstitutionMap subs;
1825+
if (auto env = value->getInnermostDeclContext()
1826+
->getGenericEnvironmentOfContext()) {
1827+
subs = SubstitutionMap::getOverrideSubstitutions(
1828+
overriddenValue, value, subs);
1829+
}
18171830

1818-
return inferredIsolation(isolation.subst(subs));
1831+
return inferredIsolation(isolation.subst(subs));
1832+
}
18191833
}
18201834

18211835
// If this is an accessor, use the actor isolation of its storage
@@ -1887,6 +1901,10 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
18871901
if (!overridden)
18881902
return;
18891903

1904+
// Actor isolation doesn't matter for async handlers.
1905+
if (isAsyncHandler(value))
1906+
return;
1907+
18901908
// Determine the actor isolation of this declaration.
18911909
auto isolation = getActorIsolation(value);
18921910

test/Concurrency/global_actor_inference.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ class SuperclassWithGlobalActors {
181181
@GenericGlobalActor<Int> func f() { }
182182
@GenericGlobalActor<Int> func g() { } // expected-note{{overridden declaration is here}}
183183
func h() { }
184+
func i() { }
185+
func j() { }
184186
}
185187

186188
@GenericGlobalActor<String>
@@ -190,6 +192,20 @@ class SubclassWithGlobalActors : SuperclassWithGlobalActors {
190192
@GenericGlobalActor<String> override func g() { } // expected-error{{global actor 'GenericGlobalActor<String>'-isolated instance method 'g()' has different actor isolation from global actor 'GenericGlobalActor<Int>'-isolated overridden declaration}}
191193

192194
override func h() { } // okay: inferred to unspecified
195+
196+
func onGenericGlobalActorString() { }
197+
@GenericGlobalActor<Int> func onGenericGlobalActorInt() { }
198+
199+
@asyncHandler @GenericGlobalActor<String>
200+
override func i() { // okay to differ from superclass because it's an asyncHandler.
201+
onGenericGlobalActorString()
202+
}
203+
204+
@asyncHandler
205+
override func j() { // okay, isolated to GenericGlobalActor<String>
206+
onGenericGlobalActorString() // okay
207+
onGenericGlobalActorInt() // expected-error{{call is 'async' but is not marked with 'await'}}
208+
}
193209
}
194210

195211
// ----------------------------------------------------------------------

0 commit comments

Comments
 (0)