Skip to content

Commit 30aed66

Browse files
committed
Short-circuit GlobalActorAttributeRequest attempting to get the Source Location of a serialized decl.
When querying the attr from a serialized decl, dependning on deserialization order, getting its source-location may launch into arbitrary type-checking when querying interface types of such decls. Which, in turn, may do things like query (to print) USRs. This ends up being prone to request evaluator cycles. Because this only applies to serialized decls, we can be confident that they already fell through this checking as primaries, so, for now, to avoid cycles, we simply ignore the source location on serialized decls only. Long-term, we are planning to remove the `merge-modules` jobs, which will help with not having to deal with this scenario. Alternatively, we would need to ensure that at decl deserialization time we cache the `GlobalActorAttributeRequest` when we see this attribute, but this would require further surgery to either serialization format or the `GlobalActorAttr` model, because such caching requires access to the `DeclID` of the global actor being referenced, which is not currently easily accessible. Resolves rdar://79563942
1 parent 1ca505b commit 30aed66

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,18 @@ GlobalActorAttributeRequest::evaluate(
378378
if (auto decl = subject.dyn_cast<Decl *>()) {
379379
dc = decl->getDeclContext();
380380
declAttrs = &decl->getAttrs();
381-
loc = decl->getLoc();
381+
// HACK: `getLoc`, when querying the attr from a serialized decl,
382+
// dependning on deserialization order, may launch into arbitrary
383+
// type-checking when querying interface types of such decls. Which,
384+
// in turn, may do things like query (to print) USRs. This ends up being
385+
// prone to request evaluator cycles.
386+
//
387+
// Because this only applies to serialized decls, we can be confident
388+
// that they already went through this type-checking as primaries, so,
389+
// for now, to avoid cycles, we simply ignore the locs on serialized decls
390+
// only.
391+
// This is a workaround for rdar://79563942
392+
loc = decl->getLoc(/* SerializedOK */ false);
382393
} else {
383394
auto closure = subject.get<ClosureExpr *>();
384395
dc = closure;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public actor Bar {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -emit-module -o %t/a.swiftmodule -emit-module-source-info-path %t/a.swiftsourceinfo -primary-file %s %S/Inputs/actor_bar.swift -module-name Foo
4+
// RUN: %target-swift-frontend -emit-module -o %t/b.swiftmodule -emit-module-source-info-path %t/b.swiftsourceinfo -primary-file %S/Inputs/actor_bar.swift %s -module-name Foo
5+
// RUN: %target-swift-frontend -merge-modules -emit-module -o %t/Foo.swiftmodule -emit-module-source-info-path %t/Foo.swiftsourceinfo %t/a.swiftmodule %t/b.swiftmodule -module-name Foo
6+
7+
extension Bar {
8+
@MainActor
9+
func bar() async throws -> Int {
10+
return 42
11+
}
12+
}

0 commit comments

Comments
 (0)