Skip to content

Commit 246e130

Browse files
authored
Merge pull request #79144 from DougGregor/distributed-typed-throws
Ensure that distributed functions with typed throws can be called from outside the actor
2 parents 65df7fc + 84ed66f commit 246e130

File tree

6 files changed

+78
-54
lines changed

6 files changed

+78
-54
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5656,9 +5656,6 @@ ERROR(distributed_actor_func_unsupported_specifier, none,
56565656
ERROR(distributed_actor_func_variadic, none,
56575657
"cannot declare variadic argument %0 in %kind1",
56585658
(DeclName, const ValueDecl *))
5659-
ERROR(distributed_actor_func_typed_throws, none,
5660-
"cannot declare distributed function with typed throws",
5661-
())
56625659
NOTE(actor_mutable_state,none,
56635660
"mutation of this %0 is only permitted within the actor",
56645661
(DescriptiveDeclKind))

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8397,8 +8397,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
83978397
// let's mark the call as implicitly throwing.
83988398
if (isDistributedThunk(callee, apply->getFn())) {
83998399
auto *FD = cast<AbstractFunctionDecl>(callee.getDecl());
8400-
if (!FD->hasThrows())
8401-
apply->setImplicitlyThrows(true);
8400+
apply->setImplicitlyThrows(true);
84028401
}
84038402

84048403
solution.setExprTypes(apply);

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,18 +3554,14 @@ namespace {
35543554
}
35553555

35563556
return std::make_pair(
3557-
/*setThrows=*/!afd->hasThrows(),
3557+
/*setThrows=*/true,
35583558
/*isDistributedThunk=*/true);
35593559
}
35603560

35613561
if (auto *var = dyn_cast<VarDecl>(decl)) {
35623562
if (var->isDistributed()) {
3563-
bool explicitlyThrowing = false;
3564-
if (auto getter = var->getAccessor(swift::AccessorKind::Get)) {
3565-
explicitlyThrowing = getter->hasThrows();
3566-
}
35673563
return std::make_pair(
3568-
/*setThrows*/ !explicitlyThrowing,
3564+
/*setThrows*/ true,
35693565
/*isDistributedThunk=*/true);
35703566
}
35713567

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -618,19 +618,6 @@ bool CheckDistributedFunctionRequest::evaluate(
618618
return true;
619619
}
620620

621-
// TODO: rdar://136467591 Currently typed throws were not implemented for distributed methods
622-
if (func->hasThrows()) {
623-
if (auto thrownError = func->getEffectiveThrownErrorType()) {
624-
// Basically we only support throwing `any Error` out of a distributed
625-
// function because then the effective error thrown by thunk calls naturally
626-
// is correct and the same `any Error`
627-
if (thrownError.has_value() &&
628-
!(*thrownError)->isEqual(C.getErrorExistentialType())) {
629-
func->diagnose(diag::distributed_actor_func_typed_throws);
630-
}
631-
}
632-
}
633-
634621
return false;
635622
}
636623

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-swift-frontend -emit-sil -DMAKE_CORRECT %s -o - | %FileCheck %s
3+
4+
// UNSUPPORTED: back_deploy_concurrency
5+
// REQUIRES: concurrency
6+
// REQUIRES: distributed
7+
8+
import Distributed
9+
10+
typealias DefaultDistributedActorSystem = LocalTestingDistributedActorSystem
11+
12+
distributed actor Foo {
13+
distributed func alwaysThrows() throws(FooError) { }
14+
15+
func alwaysPropagates() throws(FooError) {
16+
// okay, produces FooError
17+
try alwaysThrows()
18+
_ = try value
19+
}
20+
21+
distributed var value: String {
22+
get throws(FooError) {
23+
throw FooError()
24+
}
25+
}
26+
}
27+
28+
struct FooError: Codable, Error { }
29+
struct RemoteInvocationError: Codable, Error { }
30+
31+
#if !MAKE_CORRECT
32+
func testBad(foo: Foo) async throws(FooError) {
33+
try await foo.alwaysThrows() // expected-error{{thrown expression type 'any Error' cannot be converted to error type 'FooError'}}
34+
35+
_ = try await foo.value // expected-error{{thrown expression type 'any Error' cannot be converted to error type 'FooError'}}
36+
}
37+
38+
func testBadDoCatch(foo: Foo) async throws {
39+
do {
40+
try await foo.alwaysThrows()
41+
_ = try await foo.value
42+
} catch let error {
43+
let _: Int = error // expected-error{{cannot convert value of type 'any Error' to specified type 'Int'}}
44+
}
45+
}
46+
#endif
47+
48+
// Distributed thunk for calling alwaysThrows() handles the translation.
49+
// CHECK-LABEL: sil hidden [thunk] [distributed] [ref_adhoc_requirement_witness "$s11Distributed29LocalTestingInvocationDecoderC18decodeNextArgumentxyKSeRzSERzlF"] @$s30distributed_actor_typed_throws3FooC12alwaysThrowsyyYaKFTE
50+
// CHECK: [[LOCAL_FN:%.*]] = function_ref @$s30distributed_actor_typed_throws3FooC12alwaysThrowsyyAA0E5ErrorVYKF : $@convention(method) (@sil_isolated @guaranteed Foo) -> @error FooError
51+
// CHECK-NEXT: hop_to_executor [[FOO:%[0-9]+]]
52+
// CHECK-NEXT: try_apply [[LOCAL_FN]]([[FOO]]) : $@convention(method) (@sil_isolated @guaranteed Foo) -> @error FooError, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
53+
// CHECK: [[ERROR_BB]]([[FOO_ERROR:%.*]] : $FooError):
54+
// CHECK: alloc_existential_box $any Error, $FooError
55+
// CHECK-NEXT: project_existential_box $FooError
56+
// CHECK: store [[FOO_ERROR]]
57+
58+
// CHECK-LABEL: sil hidden @$s30distributed_actor_typed_throws8testGood3fooyAA3FooC_tYaKF : $@convention(thin) @async (@guaranteed Foo) -> @error any Error
59+
func testGood(foo: Foo) async throws {
60+
// CHECK: function_ref @$s30distributed_actor_typed_throws3FooC12alwaysThrowsyyYaKFTE : $@convention(method) @async (@guaranteed Foo) -> @error any Error
61+
try await foo.alwaysThrows()
62+
63+
_ = try await foo.value
64+
}
65+
66+
func testDoCatch(foo: Foo) async throws(FooError) {
67+
do {
68+
try await foo.alwaysThrows()
69+
_ = try await foo.value
70+
} catch let error {
71+
if let fe = error as? FooError {
72+
throw fe
73+
}
74+
}
75+
}

test/Distributed/distributed_actor_unsupported_typed_throws.swift

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)