// RUN: %target-swift-frontend -emit-sil -parse-as-library -target %target-swift-5.1-abi-triple -strict-concurrency=complete -verify -verify-additional-prefix ni- %s -o /dev/null -enable-upcoming-feature GlobalActorIsolatedTypesUsability // RUN: %target-swift-frontend -emit-sil -parse-as-library -target %target-swift-5.1-abi-triple -strict-concurrency=complete -verify -verify-additional-prefix ni-ns- %s -o /dev/null -enable-upcoming-feature GlobalActorIsolatedTypesUsability -enable-upcoming-feature NonisolatedNonsendingByDefault // REQUIRES: concurrency // REQUIRES: swift_feature_GlobalActorIsolatedTypesUsability // REQUIRES: swift_feature_NonisolatedNonsendingByDefault //////////////////////// // MARK: Declarations // //////////////////////// class NonSendableKlass { func use() {} } struct NonSendableStruct { var first = NonSendableKlass() var second = NonSendableKlass() } class KlassWithNonSendableStructPair { var ns1: NonSendableStruct var ns2: (NonSendableStruct, NonSendableStruct) init() { ns1 = NonSendableStruct() ns2 = (ns1, ns1) } } final class FinalKlassWithNonSendableStructPair { var ns1: NonSendableStruct var ns2: (NonSendableStruct, NonSendableStruct) init() { ns1 = NonSendableStruct() ns2 = (ns1, ns1) } } func useValue(_ t: T) {} func getAny() -> Any { fatalError() } actor Custom { } @globalActor struct CustomActor { static var shared: Custom { return Custom() } } @MainActor func transferToMain(_ t: T) {} @CustomActor func transferToCustom(_ t: T) {} func throwingFunction() throws { fatalError() } func transferArg(_ x: sending NonSendableKlass) { } func transferArgAsync(_ x: sending NonSendableKlass) async { } func transferArgWithOtherParam(_ x: sending NonSendableKlass, _ y: NonSendableKlass) { } func transferArgWithOtherParam2(_ x: NonSendableKlass, _ y: sending NonSendableKlass) { } func twoTransferArg(_ x: sending NonSendableKlass, _ y: sending NonSendableKlass) {} @MainActor var globalKlass = NonSendableKlass() struct MyError : Error {} func takeClosure(_ x: sending () -> ()) {} func takeClosureAndParam(_ x: NonSendableKlass, _ y: sending () -> ()) {} ///////////////// // MARK: Tests // ///////////////// func testSimpleTransferLet() { let k = NonSendableKlass() transferArg(k) // expected-warning {{sending 'k' risks causing data races}} // expected-note @-1 {{'k' used after being passed as a 'sending' parameter}} useValue(k) // expected-note {{access can happen concurrently}} } func testSimpleTransferVar() { var k = NonSendableKlass() k = NonSendableKlass() transferArg(k) // expected-warning {{sending 'k' risks causing data races}} // expected-note @-1 {{'k' used after being passed as a 'sending' parameter}} useValue(k) // expected-note {{access can happen concurrently}} } func testSimpleTransferUseOfOtherParamNoError() { let k = NonSendableKlass() let k2 = NonSendableKlass() transferArgWithOtherParam(k, k2) useValue(k2) } func testSimpleTransferUseOfOtherParamNoError2() { let k = NonSendableKlass() let k2 = NonSendableKlass() transferArgWithOtherParam2(k, k2) useValue(k) } @MainActor func transferToMain2(_ x: sending NonSendableKlass, _ y: NonSendableKlass, _ z: NonSendableKlass) async { } // TODO: How to test this? func testNonStrongTransferDoesntMerge() async { } ////////////////////////////////// // MARK: Transferring Parameter // ////////////////////////////////// func testTransferringParameter_canTransfer(_ x: sending NonSendableKlass, _ y: NonSendableKlass) async { await transferToMain(x) await transferToMain(y) // expected-warning {{sending 'y' risks causing data races}} // expected-note @-1 {{sending task-isolated 'y' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and task-isolated uses}} } func testTransferringParameter_cannotTransferTwice(_ x: sending NonSendableKlass, _ y: NonSendableKlass) async { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} // TODO: We should not error on this since we are sending to the same place. await transferToMain(x) // expected-note {{access can happen concurrently}} } func testTransferringParameter_cannotUseAfterTransfer(_ x: sending NonSendableKlass, _ y: NonSendableKlass) async { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} useValue(x) // expected-note {{access can happen concurrently}} } actor MyActor { var field = NonSendableKlass() func canTransferWithTransferringMethodArg(_ x: sending NonSendableKlass, _ y: NonSendableKlass) async { await transferToMain(x) await transferToMain(y) // expected-warning {{sending 'y' risks causing data races}} // expected-note @-1 {{sending 'self'-isolated 'y' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and 'self'-isolated uses}} } func getNormalErrorIfTransferTwice(_ x: sending NonSendableKlass) async { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local actor-isolated uses}} await transferToMain(x) // expected-note {{access can happen concurrently}} } func getNormalErrorIfUseAfterTransfer(_ x: sending NonSendableKlass) async { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local actor-isolated uses}} useValue(x) // expected-note {{access can happen concurrently}} } // After assigning into the actor, we can still use x in the actor as long as // we don't transfer it. func assignTransferringIntoActor(_ x: sending NonSendableKlass) async { field = x useValue(x) } // Once we assign into the actor, we cannot transfer further. func assignTransferringIntoActor2(_ x: sending NonSendableKlass) async { field = x await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'self'-isolated 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and 'self'-isolated uses}} } } @MainActor func canAssignTransferringIntoGlobalActor(_ x: sending NonSendableKlass) async { globalKlass = x } @MainActor func canAssignTransferringIntoGlobalActor2(_ x: sending NonSendableKlass) async { globalKlass = x // TODO: This is incorrect! sending should be independent of @MainActor. await transferToCustom(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending main actor-isolated 'x' to global actor 'CustomActor'-isolated global function 'transferToCustom' risks causing data races between global actor 'CustomActor'-isolated and main actor-isolated uses}} } @MainActor func canAssignTransferringIntoGlobalActor3(_ x: sending NonSendableKlass) async { await transferToCustom(globalKlass) // expected-warning {{sending value of non-Sendable type 'NonSendableKlass' risks causing data races}} // expected-note @-1 {{sending main actor-isolated value of non-Sendable type 'NonSendableKlass' to global actor 'CustomActor'-isolated global function 'transferToCustom' risks causing races in between main actor-isolated and global actor 'CustomActor'-isolated uses}} } func canTransferAssigningIntoLocal(_ x: sending NonSendableKlass) async { let _ = x await transferToMain(x) } func canTransferAssigningIntoLocal2(_ x: sending NonSendableKlass) async { let _ = x await transferToMain(x) // We do not error here since we just load the value and do not do anything // with it. // // TODO: We should change let _ = x so that it has a move_value '_' or // something like that. It will also help move checking as well. let _ = x } func canTransferAssigningIntoLocal2a(_ x: sending NonSendableKlass) async { let _ = x await transferToMain(x) // We do not error here since we just load the value and do not do anything // with it. // // TODO: We should change let _ = x so that it has a move_value '_' or // something like that. It will also help move checking as well. _ = x } func canTransferAssigningIntoLocal3(_ x: sending NonSendableKlass) async { let _ = x await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} let y = x // expected-note {{access can happen concurrently}} _ = y } ////////////////////////////////////// // MARK: Transferring is "var" like // ////////////////////////////////////// // Assigning into a 'sending' parameter is a merge. func assigningIsAMerge(_ x: sending NonSendableKlass) async { let y = NonSendableKlass() x = y // We can still transfer y since x is disconnected. await transferToMain(y) } func assigningIsAMergeError(_ x: sending NonSendableKlass) async { let y = NonSendableKlass() x = y // We can still transfer y since x is disconnected. await transferToMain(y) // expected-warning {{sending 'y' risks causing data races}} // expected-note @-1 {{sending 'y' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} useValue(x) // expected-note {{access can happen concurrently}} } func assigningIsAMergeAny(_ x: sending Any) async { // Ok, this is disconnected. let y = getAny() x = y await transferToMain(y) } func assigningIsAMergeAnyError(_ x: sending Any) async { // Ok, this is disconnected. let y = getAny() x = y await transferToMain(y) // expected-warning {{sending 'y' risks causing data races}} // expected-note @-1 {{sending 'y' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} useValue(x) // expected-note {{access can happen concurrently}} } func canTransferAfterAssign(_ x: sending Any) async { // Ok, this is disconnected. let y = getAny() // y is transferred into x. await transferToMain(x) x = y useValue(x) } func canTransferAfterAssignButUseIsError(_ x: sending Any) async { // Ok, this is disconnected. let y = getAny() // y is transferred into x. x = y // TODO: This should refer to the sending parameter. await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} useValue(x) // expected-note {{access can happen concurrently}} } func assignToEntireValueEliminatesEarlierTransfer(_ x: sending Any) async { // Ok, this is disconnected. let y = getAny() useValue(x) // Transfer x await transferToMain(x) // y is transferred into x. This shouldn't error. x = y useValue(x) } func mergeDoesNotEliminateEarlierTransfer(_ x: sending NonSendableStruct) async { // Ok, this is disconnected. let y = NonSendableKlass() useValue(x) // Transfer x await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} // y is assigned into a field of x. x.first = y // expected-note {{access can happen concurrently}} useValue(x) } func mergeDoesNotEliminateEarlierTransfer2(_ x: sending NonSendableStruct) async { // Ok, this is disconnected. let y = NonSendableKlass() useValue(x) // Transfer x await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} x.first = y // expected-note {{access can happen concurrently}} } func doubleArgument() async { let x = NonSendableKlass() twoTransferArg(x, x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{'x' used after being passed as a 'sending' parameter}} // expected-note @-2 {{access can happen concurrently}} } func testTransferSrc(_ x: sending NonSendableKlass) async { let y = NonSendableKlass() await transferToMain(y) // expected-warning {{sending 'y' risks causing data races}} // expected-note @-1 {{sending 'y' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} x = y // expected-note {{access can happen concurrently}} } func testTransferOtherParam(_ x: sending NonSendableKlass, y: NonSendableKlass) async { x = y } func testTransferOtherParamTuple(_ x: sending NonSendableKlass, y: (NonSendableKlass, NonSendableKlass)) async { x = y.0 } func fakeInitOutside(operation: sending @escaping () async -> ()) {} func taskIsolatedOutsideError(_ x: @escaping @MainActor () async -> ()) { fakeInitOutside(operation: x) // okay; x is @Sendable } @MainActor func actorIsolatedOutsideError(_ x: @escaping @MainActor () async -> ()) { fakeInitOutside(operation: x) // okay; x is @Sendable } func taskIsolatedInsideError(_ x: @escaping @MainActor () async -> ()) { func fakeInit(operation: sending @escaping () async -> ()) {} fakeInit(operation: x) // okay; x is @Sendable } @MainActor func actorIsolatedInsideError(_ x: @escaping @MainActor () async -> ()) { func fakeInit(operation: sending @escaping () async -> ()) {} // We do not get an error here since fakeInit is MainActor isolated since it // is defined within this function. As a result, we are sending a @MainActor // isolated thing to a MainActor-isolated thing. fakeInit(operation: x) } // Make sure we error here on only the second since x by being assigned a part // of y becomes task-isolated func testMergeWithTaskIsolated(_ x: sending NonSendableKlass, y: NonSendableKlass) async { await transferToMain(x) x = y await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending task-isolated 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and task-isolated uses}} } @MainActor func testMergeWithActorIsolated(_ x: sending NonSendableKlass, y: NonSendableKlass) async { x = y await transferToCustom(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending main actor-isolated 'x' to global actor 'CustomActor'-isolated global function 'transferToCustom' risks causing data races between global actor 'CustomActor'-isolated and main actor-isolated uses}} } @available(SwiftStdlib 5.1, *) actor NonSendableInit { var first: NonSendableKlass var second: NonSendableKlass? = nil { @storageRestrictions(initializes: first) init(initialValue) { transferArg(initialValue!) // expected-warning {{sending 'initialValue' risks causing data races}} // expected-note @-1 {{'self'-isolated 'initialValue' is passed as a 'sending' parameter}} first = initialValue! } get { fatalError() } set { fatalError() } } } func testNoCrashWhenSendingNoEscapeClosure() async { func test(_ x: sending () -> ()) async {} let c = NonSendableKlass() await test { print(c) } } /////////////////////////////// // MARK: InOut Sending Tests // /////////////////////////////// func testInOutSendingReinit(_ x: inout sending NonSendableKlass) async { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} } // expected-note {{'inout sending' parameter must be reinitialized before function exit with a non-actor-isolated value}} func testInOutSendingReinit2(_ x: inout sending NonSendableKlass) async { await transferToMain(x) x = NonSendableKlass() } func testInOutSendingReinit3(_ x: inout sending NonSendableKlass) async throws { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} try throwingFunction() // expected-note {{'inout sending' parameter must be reinitialized before function exit with a non-actor-isolated value}} x = NonSendableKlass() } func testInOutSendingReinit4(_ x: inout sending NonSendableKlass) async throws { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} do { try throwingFunction() x = NonSendableKlass() } catch { throw MyError() // expected-note {{'inout sending' parameter must be reinitialized before function exit with a non-actor-isolated value}} } x = NonSendableKlass() } func testInOutSendingReinit5(_ x: inout sending NonSendableKlass) async throws { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} do { try throwingFunction() } catch { throw MyError() // expected-note {{'inout sending' parameter must be reinitialized before function exit with a non-actor-isolated value}} } x = NonSendableKlass() } func testInOutSendingReinit6(_ x: inout sending NonSendableKlass) async throws { await transferToMain(x) // expected-warning {{sending 'x' risks causing data races}} // expected-note @-1 {{sending 'x' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} do { try throwingFunction() } catch { throw MyError() // expected-note {{'inout sending' parameter must be reinitialized before function exit with a non-actor-isolated value}} } } // expected-note {{'inout sending' parameter must be reinitialized before function exit with a non-actor-isolated value}} actor InOutSendingWrongIsolationActor { var ns = NonSendableKlass() func testWrongIsolation(_ x: inout sending NonSendableKlass) { x = ns } // expected-warning {{'inout sending' parameter 'x' cannot be 'self'-isolated at end of function}} // expected-note @-1 {{'self'-isolated 'x' risks causing races in between 'self'-isolated uses and caller uses since caller assumes value is not actor isolated}} func testWrongIsolation2(_ x: inout sending NonSendableKlass) { let z = ns x = z } // expected-warning {{'inout sending' parameter 'x' cannot be 'self'-isolated at end of function}} // expected-note @-1 {{'self'-isolated 'x' risks causing races in between 'self'-isolated uses and caller uses since caller assumes value is not actor isolated}} } @MainActor func testWrongIsolationGlobalIsolation(_ x: inout sending NonSendableKlass) { x = globalKlass } // expected-warning {{'inout sending' parameter 'x' cannot be main actor-isolated at end of function}} // expected-note @-1 {{main actor-isolated 'x' risks causing races in between main actor-isolated uses and caller uses since caller assumes value is not actor isolated}} func taskIsolatedCaptureInSendingClosureLiteral(_ x: NonSendableKlass) { Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}} print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}} } Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}} { print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}} }() } Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}} { // expected-note {{closure captures 'x' which is accessible to code in the current task}} print($0) }(x) } takeClosure { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}} print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}} } takeClosureAndParam(NonSendableKlass()) { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}} print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}} } let y = (x, x) Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}} print(y) // expected-note {{closure captures 'y' which is accessible to code in the current task}} } let z = (x, y) Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}} print(y, z) // expected-note @:11 {{closure captures non-Sendable 'y'}} // expected-note @-1:14 {{closure captures non-Sendable 'z'}} } } extension MyActor { func actorIsolatedCaptureInSendingClosureLiteral(_ x: NonSendableKlass) { Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}} print(x) // expected-note {{closure captures 'self'-isolated 'x'}} } takeClosure { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}} print(x) // expected-note {{closure captures 'self'-isolated 'x'}} } takeClosureAndParam(NonSendableKlass()) { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}} print(x) // expected-note {{closure captures 'self'-isolated 'x'}} } let y = (x, x) Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}} print(y) // expected-note {{closure captures 'y' which is accessible to 'self'-isolated code}} } let z = (x, y) Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}} print(y, z) // expected-note @:13 {{closure captures non-Sendable 'y'}} // expected-note @-1:16 {{closure captures non-Sendable 'z'}} } } } // We would normally not error here since transferArg is nonisolated and c is // disconnected. Since c is passed as sending, we shouldn't squelch this. func disconnectedPassedSendingToNonIsolatedCallee( ) async -> Void { let c = NonSendableKlass() transferArg(c) // expected-warning {{sending 'c' risks causing data races}} // expected-note @-1 {{'c' used after being passed as a 'sending' parameter}} c.use() // expected-note {{access can happen concurrently}} } // We would normally not error here since transferArg is nonisolated and c is // disconnected. Since c is passed as sending, we shouldn't squelch this. func disconnectedPassedSendingToAsyncNonIsolatedCallee( ) async -> Void { let c = NonSendableKlass() await transferArgAsync(c) // expected-warning {{sending 'c' risks causing data races}} // expected-note @-1 {{'c' used after being passed as a 'sending' parameter}} c.use() // expected-note {{access can happen concurrently}} } // We would normally not error here since transferArg is nonisolated and c is // disconnected. Since c is passed as sending, we shouldn't squelch this. func disconnectedPassedSendingToNonIsolatedCalleeIsolatedParam2( isolation: isolated (any Actor)? = nil ) async -> Void { let c = NonSendableKlass() transferArg(c) // expected-warning {{sending 'c' risks causing data races}} // expected-note @-1 {{'c' used after being passed as a 'sending' parameter}} c.use() // expected-note {{access can happen concurrently}} } // We would normally not error here since transferArg is nonisolated and c is // disconnected. Since c is passed as sending, we shouldn't squelch this. func disconnectedPassedSendingToAsyncNonIsolatedCalleeIsolatedParam2( isolation: isolated (any Actor)? = nil ) async -> Void { let c = NonSendableKlass() await transferArgAsync(c) // expected-warning {{sending 'c' risks causing data races}} // expected-note @-1 {{'c' used after being passed as a 'sending' parameter}} c.use() // expected-note {{access can happen concurrently}} } // We would normally not error here since transferArg is nonisolated and c is // disconnected. Since c is passed as sending, we shouldn't squelch this. func disconnectedPassedSendingToNonIsolatedCalleeIsolatedParam3( isolation: isolated (any Actor)? = nil ) -> Void { let c = NonSendableKlass() transferArg(c) // expected-warning {{sending 'c' risks causing data races}} // expected-note @-1 {{'c' used after being passed as a 'sending' parameter}} c.use() // expected-note {{access can happen concurrently}} } // In all of the below, we don't know that 'a' is the same isolation as the // closure isolation. func testNonSendableCaptures(ns: NonSendableKlass, a: isolated MyActor) { Task { _ = a _ = ns } Task { [a] in // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'a'-isolated code and concurrent execution of the closure}} _ = a _ = ns // expected-note {{closure captures 'a'-isolated 'ns'}} } Task { let _ = a let _ = ns } Task { [a] in // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'a'-isolated code and concurrent execution of the closure}} let _ = a let _ = ns // expected-note {{closure captures 'a'-isolated 'ns'}} } Task { [a] in // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'a'-isolated code and concurrent execution of the closure}} let (_, _) = (a, ns) // expected-note {{closure captures 'a'-isolated 'ns'}} let _ = ns } }