@@ -146,7 +146,7 @@ public enum FileMode: Sendable {
146146/// substitute a virtual file system or redirect file system operations.
147147///
148148/// - Note: All of these APIs are synchronous and can block.
149- public protocol FileSystem : AnyObject {
149+ public protocol FileSystem : AnyObject , Sendable {
150150 /// Check whether the given path exists and is accessible.
151151 func exists( _ path: AbsolutePath , followSymlink: Bool ) -> Bool
152152
@@ -548,8 +548,6 @@ private class LocalFileSystem: FileSystem {
548548 }
549549}
550550
551- // FIXME: This class does not yet support concurrent mutation safely.
552- //
553551/// Concrete FileSystem implementation which simulates an empty disk.
554552public class InMemoryFileSystem : FileSystem {
555553
@@ -1008,6 +1006,9 @@ public class InMemoryFileSystem: FileSystem {
10081006 }
10091007}
10101008
1009+ // Internal state of `InMemoryFileSystem` is protected with a lock in all of its `public` methods.
1010+ extension InMemoryFileSystem : @unchecked Sendable { }
1011+
10111012/// A rerooted view on an existing FileSystem.
10121013///
10131014/// This is a simple wrapper which creates a new FileSystem view into a subtree
@@ -1159,9 +1160,16 @@ public class RerootedFileSystemView: FileSystem {
11591160 }
11601161}
11611162
1163+ // `RerootedFileSystemView` doesn't hold any internal state and can be considered `Sendable` since
1164+ // `underlyingFileSystem` is required to be `Sendable`.
1165+ extension RerootedFileSystemView : @unchecked Sendable { }
1166+
11621167/// Public access to the local FS proxy.
11631168public var localFileSystem : FileSystem = LocalFileSystem ( )
11641169
1170+ // `LocalFileSystem` doesn't hold any internal state and all of its underlying operations are blocking.
1171+ extension LocalFileSystem : @unchecked Sendable { }
1172+
11651173extension FileSystem {
11661174 /// Print the filesystem tree of the given path.
11671175 ///
0 commit comments