|
| 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 | +} |
0 commit comments