Fixing “Worth of non-Sendable kind accessed after being transferred; later accesses may race;” – Donny Wals


Revealed on: August 23, 2024

When you begin migrating to the Swift 6 language mode, you will most definitely activate strict concurrency first. As soon as you’ve got accomplished this there might be a number of warings and errors that you will encounter and these errors will be complicated at instances.

I will begin by saying that having a strong understanding of actors, sendable, and information races is a large benefit once you wish to undertake the Swift 6 language mode. Just about all the warnings you will get in strict concurrency mode will let you know about potential points associated to working code concurrently. For an in-depth understanding of actors, sendability and information races I extremely advocate that you just check out my Swift Concurrency course which is able to get you entry to a sequence of movies, workout routines, and my Sensible Swift Concurrency ebook with a single buy.

WIth that out of the way in which, let’s check out the next warning that you just would possibly encounter in your challenge:

Worth of non-Sendable kind ‘MyType’ accessed after being transferred; later accesses may race;

For instance, the next code produces such an error:

var myArray = [Int]()

Activity {
  // Worth of non-Sendable kind '@remoted(any) @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <()>' accessed after being transferred; later accesses may race;
  myArray.append(1)
}

myArray.append(2)

Xcode gives just a little steerage as to what that error is telling us:

Entry can occur concurrently

In different phrases, the compiler is telling us that we’re accessing myArray after we have “transferred” that property to our Activity. You’ll be able to see how we’re appending to the array each inside the duty in addition to outdoors of it.

Swift is telling us that we’re doubtlessly inflicting information races right here as a result of our append on myArray after the duty would possibly really collide with the append inside of the duty. When this occurs, we’ve got an information race and our code would crash.

The repair right here can be to explicitly make a duplicate for our activity when it is created:

Activity { [myArray] in
  var myArray = myArray
  myArray.append(1)
}

This eliminates our information race potential however it’s additionally probably not attaining our purpose of appending to the array from inside the duty.

The repair right here could possibly be considered one of a number of approaches:

  1. You’ll be able to wrapp your array in an actor to make sure correct isolation and synchronization
  2. You’ll be able to rework your strategy completely
  3. International actors could possibly be helpful right here relying on the construction of your code

In the end, most strict concurrency associated points do not have a single answer that works. It is at all times going to require a case-by-case evaluation of why a sure error seems, and from there you need to determine an answer.

On this case, we’re taking a mutable object that we’re mutating from inside a activity in addition to proper after the place we have outlined the duty. The compiler is warning us that that may most definitely trigger an information race and you will want to find out which answer works for you. My first try at fixing this may be to wrap the mutable state in an actor to verify we obtain correct isolation and stop future information races.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles