Why doesn't inherited isolation work with this code snippet?

I have a function:

private class BindingTracer {
  @TaskLocal static var locationStack: [Location] = []

  static let thisFileID: StaticString = #fileID

  static func withLocation<T>(
    isolation: isolated (any Actor)? = #isolation,
    _ location: Location, _ body: () async throws -> T
  ) async rethrows -> T {
    var newStack = Self.locationStack
    if location.fileID.description == thisFileID.description {
      // TODO: its not clear why this works, and why we can't simply return try await body() instead
      return try await $locationStack.withValue(newStack) {
        try await body()
      }
    }

    newStack.append(location)
    return try await $locationStack.withValue(newStack) {
      try await body()
    }
  }
}

The code compiles as written above. However if we simplify the portion in the if ... statement and remove the unneeded try await $locationStack.withValue to this:

if location.fileID.description == thisFileID.description {
  try await body()
}

The code no longer compiles in Swift 6 with the following error: Non-sendable type 'T' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary. Can someone help me understand why this is the case?

1 Like