# Pitch 2: Add FilePath to stdlib

**URL:** <https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695>\
**Category:** Pitches\
**Created:** [March 30, 2026, 4:00pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695 "2026-03-30T16:00:50Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![Michael\_Ilseman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michael_ilseman/32/44640_2.png) [@Michael\_Ilseman](https://forums.swift.org/u/Michael_Ilseman)\
**Post date:** [March 30, 2026, 4:00pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/1 "2026-03-30T16:00:50Z")

</div>

Hello all, I've written a second draft for inclusion of FilePath in the stdlib. I've trimmed many of the syntactic operations, focusing on what is essential to get in Swift: the types, fundamental conformances, and behavior fixes (like trailing slash). Future proposals can include many of the convenience methods.

Full proposal viewable at [FilePath in the stdlib - pitch 2 · GitHub](https://gist.github.com/milseman/438cd1566a2ac7ba20b36b383da05aaf)

* * *

# Add `FilePath` to the Standard Library

- Proposal: TBD
- Authors: [Michael Ilseman](https://github.com/milseman), [Saleem Abdulrasool](https://github.com/compnerd)
- Review Manager: TBD
- Status: **Pitch**
- Implementation: TBD
- Review: TBD

## Introduction

We propose adding `FilePath` and its essential operations to the Swift standard library. `FilePath` parses platform-specific path syntax on the developer's behalf, provides a normalized view of path components, and enables resolution against the filesystem. This proposal focuses on establishing the core type, its conformances, and the essential operations needed to adopt it as a currency type. Additional syntactic convenience methods and platform-specific path decomposition API are planned as future additions. See Future Directions.

## Motivation

Swift has no standard representation for file system paths. The swift-system package introduced `FilePath` in [System 0.0.1](https://github.com/apple/swift-system/releases/tag/0.0.1), and it has since gained a comprehensive set of [syntactic operations](https://forums.swift.org/t/api-review-filepath-syntactic-apis-version-2/44197) for platform-correct path manipulation. But because `FilePath` lives in an external package, it cannot be depended on by the standard library or the Swift runtime, nor can it appear in API in toolchain libraries such as Foundation.

Every new API that needs to name a file path faces the same dilemma around using `String` that [SE-0513](https://forums.swift.org/t/se-0513-api-to-get-the-path-to-the-current-executable/84800) faces. `String` is a poor fit for paths as it does not capture the structure of a file path. Path string representations are also platform-specific and path components are not necessarily valid Unicode.

`FilePath` stores the path in its native platform encoding, enabling strongly-typed programming with paths. It encapsulates the platform-specific details of path syntax (separators, root/prefix forms, special components) so that developers can work with paths correctly without needing to understand each platform's conventions.

## Proposed solution

We propose adding `FilePath`, `FilePath.Component`, and `FilePath.ComponentView` to the `Swift` module, alongside essential functionality for construction, decomposition, resolution, and C interoperability.

```swift
var path: FilePath = "/var/www/static/index.html"

path.isAbsolute // true
path.hasTrailingSeparator // false

for component in path.components {
    print(component, component.kind) // "var": .regular, "www": .regular, ...
}

// Resolve against the filesystem
let resolved = try path.resolve()

// Construct a path through mutation
var config: FilePath = "/etc/nginx"
config.components.append("nginx.conf")
// config is "/etc/nginx/nginx.conf"

```

## Detailed design

See [full proposal](https://gist.github.com/milseman/438cd1566a2ac7ba20b36b383da05aaf)

## Source compatibility

All changes are additive.

`SystemPackage.FilePath` and/or `System.FilePath` can migrate to the standard library's `FilePath` via a conditional typealias:

```swift
#if compiler(>=6.4) // or whichever version this lands in
public typealias FilePath = Swift.FilePath
#else
public struct FilePath { ... }
#endif

```

Existing functionality from `SystemPackage.FilePath` (such as syntactic convenience methods) can be added as extensions on `Swift.FilePath` on toolchain versions that include this change. This enables a smooth source-compatible migration path.

## ABI compatibility

This proposal is purely an extension of the ABI of the standard library and does not change any existing features.

On Darwin, `System.FilePath` currently has ABI commitments. Migration from the System module on Darwin can be handled through ABI-level redirection so that existing binaries linked against `System.FilePath` continue to work.

## Implications on adoption

Adopters will need a toolchain that includes this change. The type cannot be back-deployed to older runtimes without additional work.

For existing users of swift-system, `SystemPackage` (the SwiftPM package) can use `#if` conditionals as described above. `System` (the Darwin framework) can perform ABI migration, redirecting the existing `System.FilePath` symbol to the standard library implementation, preserving binary compatibility for existing Darwin binaries.

## Future directions

### Syntactic operations and path decomposition

Future API for `FilePath` could include additional syntactic operations and more path decomposition, such as [originally pitched](https://forums.swift.org/t/pitch-add-filepath-to-the-standard-library/84812). This includes convenience accessors like `lastComponent`, `stem`, `extension`, `removingLastComponent()`, and mutation methods like `append`, `push`, `removePrefix`. These can be expressed in terms of the `ComponentView` and are back-deployable.

### Lexical resolution and resolve-beneath

Lexical operations that collapse `..` components without consulting the filesystem, and operations that ensure a subpath does not escape a base directory, are important for sandboxing and security-sensitive code. These were part of the original pitch and are planned as future additions. Real resolution (via `resolve()`) is provided in this proposal to ensure developers have the correct tool available from day one.

### Path prefix type and analysis

Windows path prefixes and Darwin roots carry more semantic content than Linux. A future `FilePath.Prefix` type could expose this structure: UNC server/share decomposition, XNU resolve flags, Windows volume identifiers, and more. The `isAbsolute`, `isRooted`, and `driveLetter` queries in this proposal cover the most common needs while the design of a full prefix type matures.

### Platform string APIs and `CInterop`

swift-system defines a `CInterop` namespace with typealiases for platform-specific character types (`PlatformChar`, `PlatformUnicodeEncoding`) and provides `init(platformString:)` APIs on `FilePath` and its subtypes. This proposal provides `withCString`/`withWCString` for passing paths to C APIs, and `Span`-based access on components. Future work could include a `PlatformChar` typealias and more functionality along these lines.

### Path parsing APIs and verbatim storage modes

Future work includes exposing `FilePath`'s internal parser for uses over borrowed storage (such as `Span`), allowing developers to parse paths in-place without copying into a `FilePath`.

Some use cases (logging, diagnostics) benefit from preserving the exact bytes of a path as originally provided, without any normalization. These would be better handled by referring to the actual original, possibly facilitated with path parsing API over borrowed storage. But, if it proves to be an essential use case, `FilePath` as pitched is sufficiently resilient that we could add a verbatim storage mode in the future.

### `SystemString`

swift-system internally uses a `SystemString` type that handles the underlying storage for `FilePath`. A similar type may be independently useful as a public type for working with null-terminated platform-encoded strings with opaque contents.

### More path types and filesystem-specific functionality

Future work could include a paths library or package that adds:

- Type-enforced invariants: `AbsolutePath`, `ResolvedPath`, etc.
- Platform-specific foreign path types: `XNUPath`, `Win32Path`, `WinNTPath`, etc.
- File-system specific (and configuration specific) functionality over components: case conversion, Unicode normalization, etc.

Testing Windows path behavior on Linux/macOS (and vice versa) is a known gap that platform-specific path types could address; these could conform to a common protocol while each implementing the semantics of its target platform.

### Legacy device name handling

On Windows, legacy device names (`CON`, `NUL`, `COM1`, etc.) receive special treatment from the Win32 layer, and their exact handling varies across Windows versions. Future work could add detection or mitigation for these names, potentially as part of a resolve-beneath or sandboxing API.

## Alternatives considered

### Do more in Swift 6.4

The [original pitch](https://forums.swift.org/t/pitch-add-filepath-to-the-standard-library/84812) included a `FilePath.Root` type, convenience methods (`lastComponent`, `stem`, `extension`, `starts(with:)`, `append`, `push`), and lexical resolution operations. We chose to defer these in favor of shipping the essential core: the type, its conformances, the component view, and real resolution. The deferred API can be added as extensions on `FilePath` and is back-deployable where expressed in terms of the component view. Shipping the type and conformances first is critical because those cannot be added retroactively without migration costs (e.g. someone conforming `FilePath` to `Hashable` themselves).

### Include `Codable` conformance

`FilePath` intentionally does not conform to `Codable`. Serialized paths are inherently platform-specific: a path serialized on Unix is not meaningful on Windows. Path prefix semantics can also change across OS versions (Windows 10 and 11 differ in device name recognition; Darwin may add new resolve flag prefixes). The existing `Codable` conformance on `System.FilePath` uses an awkward binary encoding that has been a source of friction. Rather than commit the standard library to a serialization format, we leave serialization to application-level code that can choose a format appropriate to its needs. `String(decoding:)` and `init(_ string:)` provide the necessary conversion.

### Do more: bring all of swift-system into the toolchain

As discussed in [system-in-the-toolchain](https://forums.swift.org/t/pitch-system-in-the-toolchain/84247), it may also make sense to have a `System` module in the toolchain for low-level OS interfaces and low-level currency types (like `FileDescriptor`, `Errno`, etc).

`FilePath` is different from these other types in that it transcends the entire tech stack, from kernel-level programming to high level scripts and automation. Note that we are not pulling in syscalls such as `FilePath.stat`, those will remain in System/SystemPackage.

### Add `FilePath` to a separate standard library module

`FilePath` could live in a new module (e.g. `FilePaths`, `Path`, `Files`, ...) that ships with the toolchain but requires an explicit import. Currency types lose much of their value when they require an import. `String`, `Array`, `Int`, and `Result` are all in the `Swift` module; it is our (weakly held) opinion `FilePath` should be too.

### Use Foundation's `URL`

Foundation's `URL` is designed for URI semantics, including scheme parsing and percent-encoding. File system paths and URIs have different structure and different invariants. For example, `URL(fileURLWithPath:)` and `URL.appendingPathComponent` make blocking file system calls, which is surprising for what appears to be a pure data type. On Unix, paths containing bytes that are not valid UTF-8 cannot survive conversion to a `file://` URL, which requires percent-encoding. Foundation also sits high in the dependency stack; the Swift runtime and toolchain components cannot depend on it.

### Do nothing

Every new API that needs to name a file will continue using `String`, perpetuating the loss of structure, platform correctness, and type safety that `FilePath` was designed to address.

## Acknowledgments

Thanks to [Saleem Abdulrasool](https://github.com/compnerd) for co-authoring the original `FilePath` syntactic operations design and implementation in swift-system. Thanks to the participants in the [System-in-toolchain discussion](https://forums.swift.org/t/pitch-system-in-the-toolchain/84247), the [SE-0513 review](https://forums.swift.org/t/se-0513-api-to-get-the-path-to-the-current-executable/84800), and the [first pitch thread](https://forums.swift.org/t/pitch-add-filepath-to-the-standard-library/84812) for helping shape this proposal.

---

<div class="post-metadata">

**Author:** ![Michael\_Ilseman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michael_ilseman/32/44640_2.png) [@Michael\_Ilseman](https://forums.swift.org/u/Michael_Ilseman)\
**Post date:** [March 30, 2026, 4:11pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/2 "2026-03-30T16:11:42Z")

</div>

**Summary of changes from the [original pitch](https://forums.swift.org/t/pitch-add-filepath-to-the-standard-library/84812):**

**Focused on the essential core.** This revision ships the type, its conformances, `ComponentView` (as `BidirectionalCollection` & `RangeReplaceableCollection`), and real filesystem `resolve()`. Convenience methods (`lastComponent`, `stem`, `extension`, `append`, `push`, `starts(with:)`, etc.) are deferred as future work, back-deployable via `ComponentView`.

**`Root` type removed.** Windows paths like `C:foo` don't decompose cleanly into a root. Replaced by targeted queries: `isAbsolute`, `isRelative`, `isRooted` (new), and `driveLetter` (new). A formal `Prefix` type is future work.

**Lexical operations deferred.** `lexicallyNormalize`, `isLexicallyNormal`, and `lexicallyResolving` are removed. A real `func resolve() throws -> FilePath` replaces them.

**Trailing separators preserved.** The original pitch stripped them on construction. This revision preserves them and makes them significant for equality (`"/tmp/foo" != "/tmp/foo/"`), with API to query and manipulate them.

**ComponentView normalization specified.** The view coalesces repeated separators, converts `/` to `\` on Windows, and drops interior `.` components (except on Windows verbatim paths). `..` is always presented.

**Components are opaque byte bags.** No `stem` or `extension` on `Component`. You get a `Span` of platform bytes.

**Platform prefix handling expanded.** XNU resolve flags (`/.resolve/1/`), volume identifiers (`/.vol/1234/5678/`), and UNC trailing separators are now correctly recognized.

**Conformance changes.** `Comparable` added to `FilePath`, `Component`, and `ComponentView`. `Codable` dropped. `Span`-based byte access and C interop (`withCString`/`withWCString`) added directly.

---

<div class="post-metadata">

**Author:** ![3405691582](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/3405691582/32/10696_2.png) [@3405691582](https://forums.swift.org/u/3405691582)\
**Post date:** [March 30, 2026, 4:27pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/3 "2026-03-30T16:27:49Z")

</div>

Just wanted to note that on a brief reading, I definitely prefer the simpler approach outlined here compared to the original.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [March 30, 2026, 4:31pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/4 "2026-03-30T16:31:05Z")

</div>

Are we missing a typedef that abstracts over “platform character” here, so that we could get rid of the platform conditions from most of the interface and have API in terms of `Span<FilePath.Character>` or `Span<PlatformCharacter>` instead?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [March 30, 2026, 5:44pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/5 "2026-03-30T17:44:19Z")

</div>

> [@scanon](#):
>
> Are we missing a typedef that abstracts over “platform character” here, so that we could get rid of the platform conditions from most of the interface and have API in terms of `Span<FilePath.Character>` or `Span<PlatformCharacter>` instead?

It might make sense to avoid committing to the file path code unit being the one true "platform character" and having the type alias be `FilePath.CodeUnit` or something like that scoped to the `FilePath` type itself. (Though I'm not sure how much that gives you over the bag-of-bytes approach the proposal follows, given the minimal nature of the rest of the API here.)

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [March 30, 2026, 6:25pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/6 "2026-03-30T18:25:22Z")

</div>

> [@Joe\_Groff](#):
>
> It might make sense to avoid committing to the file path code unit being the one true "platform character" and having the type alias be `FilePath.CodeUnit` or something like that scoped to the `FilePath` type itself.

As a type alias, this does sound like the best path to me (ha).

---

<div class="post-metadata">

**Author:** ![Michael\_Ilseman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michael_ilseman/32/44640_2.png) [@Michael\_Ilseman](https://forums.swift.org/u/Michael_Ilseman)\
**Post date:** [March 30, 2026, 10:50pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/7 "2026-03-30T22:50:01Z")

</div>

I uploaded a new version of the pitch with this change and some related tweaks: [https://gist.github.com/milseman/438cd1566a2ac7ba20b36b383da05aaf/revisions](https://gist.github.com/milseman/438cd1566a2ac7ba20b36b383da05aaf/revisions)

**Summary of changes in version 2.1** :

- Added `typealias FilePath.CodeUnit = CChar/UInt16` to remove the conditionals around the spans.
- Span properties and argument labels are now named `codeUnits`
- Added `OutputSpan<FilePath.CodeUnit>` init
- `withCString` now takes a pointer of `FilePath.CodeUnit`s
- `withWCString` is now named `withCString` on Windows

---

<div class="post-metadata">

**Author:** ![arennow](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/arennow/32/27261_2.png) [@arennow](https://forums.swift.org/u/arennow)\
**Post date:** [April 6, 2026, 8:57pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/9 "2026-04-06T20:57:35Z")

</div>

I think this is a very good starting place. Given the immediate intense commentary on the last version of this pitch, and the fairly slow, gentle commentary on this one, I think we’ve landed in a good place. Your work on this topic is much appreciated

---

<div class="post-metadata">

**Author:** ![Michael\_Ilseman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michael_ilseman/32/44640_2.png) [@Michael\_Ilseman](https://forums.swift.org/u/Michael_Ilseman)\
**Post date:** [April 13, 2026, 2:57pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/10 "2026-04-13T14:57:34Z")

</div>

Hi everyone, this thread is pretty quiet and non-controversial. I urge that we consider advancing this to a formal review for inclusion in Swift 6.4.

I posted a small update to the [gist](https://gist.github.com/milseman/438cd1566a2ac7ba20b36b383da05aaf):

```swift
**Summary of changes in version 2.2** :

- Added `var nullTerminatedCodeUnits: Span<FilePath.CodeUnit>` to replace `withCString`, no unsafe pointers or closures anymore

```

This removes any use of unsafe pointers from new API by instead delegating to Span. The downside is we need to pick a name for this property, and I went with `nullTerminatedCodeUnits`. I recommend we hash out names during the formal review.

* * *

`FilePath` as proposed parses paths the way your platform's kernel parses paths, which is surprisingly non-trivial as Darwin and Windows paths have obscure features and platform-specific prefixes/suffixes. `FilePath` parses these correctly so that the developer doesn't have to, but they are semantically relevant and affect things like `==` comparisons.

I want to mention three high-value, but technically severable, additions that would help developers deal with these things when they arise (e.g. by explicitly ignoring or dropping them). Workarounds exist for all three, so it's a question for the Language Steering Group whether any are worth including in the formal review or whether they should be future work. I do not want them to hold up the start of the formal review.

These are presented here for awareness, not as a request for another round of pitch discussion. They can be evaluated during the formal review as severable additions, or deferred entirely.

**1. `FilePath.Anchor`** (cross-platform). An opaque type for the prefix region of a path, enabling `var anchor: Anchor? { get set }` and a reconstruction init `FilePath(anchor:components:hasTrailingSeparator:)`. This completes the decomposition model and provides a deprecation path for swift-system's `Root`. Without it, transplanting or replacing a path's prefix is done through the existing structured API:

```swift
var path: FilePath = #"C:\Users\dev\project"#
...

// Now we want to make it a verbatim-component path using `\\?\`

// With Anchor:
path.anchor = #"\\?\C:\"# 

// Without: construct a new path and transplant the components and anything else that's needed
var result: FilePath = #"\\?\C:\"#
result.components = path.components
if path.hasTrailingSeparator {
    result = result.withTrailingSeparator()
}
path = result

```

The workaround is functional, but it's easy to lose information in some corner cases. On Darwin, the reconstruction init using `Anchor` would similarly assist in removing or ignoring resolve flags (an internal and obscure, but semantically-meaningful and important, detail).

Python's `pathlib` has used `.anchor` for this concept since 3.4 and we consider this the better name than `Root` as `Root` is technically inaccurate for Windows paths such as `C:foo`. Rust uses the name "prefix" for this concept but it's too general to be obvious what its role is and `Sequence.prefix` exists with a somewhat different meaning.

`Anchor` would then position us for future additions either in the stdlib or a library such as swift-system or a dedicated paths module: [Future anchor additions · GitHub](https://gist.github.com/milseman/c76f878ad58ed6d2463c935f58233184)

**2. Resource fork bools** (Darwin-only). `FilePath` already correctly parses `/..namedfork/rsrc` suffixes: they affect equality/hashing and are hidden from `ComponentView`. They are not relative path components, but instead they are directly analogous to (and mutually exclusive with) trailing separators. Without any API, developers can't observe what FilePath parsed other than looking at the raw bytes or string representation. If we add `isResourceFork`, `withResourceFork()`, `withoutResourceFork()`, `removeResourceFork()`, mirroring the trailing separator pattern, then it's much easier for developers to work with or around them.

```swift
// With API:
if path.isResourceFork { path.removeResourceFork() }

// Without:
let s = String(decoding: path)
if s.hasSuffix("/..namedfork/rsrc") {
    path = FilePath(String(s.dropLast("/..namedfork/rsrc".count)))
}

```

**3. `Component.init(verbatim:)`** (Windows-only). Inside `\\?\` paths, `/` is a legal character in component names, but the standard `Component.init` rejects it. A verbatim init would allow constructing such components directly. Without it:

```swift
// Construct a throwaway path to extract the component
var temp = FilePath(#"\\?\x\weird/name"#)
let c = temp.components.last // extracts "weird/name" as one component
...

```

Feedback on any of the above is welcome. We'd like to get the core proposal into formal review soon.

---

<div class="post-metadata">

**Author:** ![Michael\_Ilseman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michael_ilseman/32/44640_2.png) [@Michael\_Ilseman](https://forums.swift.org/u/Michael_Ilseman)\
**Post date:** [April 21, 2026, 1:02pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/11 "2026-04-21T13:02:35Z")

</div>

I updated the [S-E PR](https://github.com/swiftlang/swift-evolution/pull/3139) with the formal proposal. I believe this is ready to run.

**Summary of changes in proposal version 1.0** :

- Added `FilePath.Anchor` as a fundamental decomposition primitive (and a replacement for swift-system's `Root` type), exposing `isRooted`, `driveLetter`, and `isVerbatimComponent`.
- Added `FilePath.Component.init(verbatim:)` overloads for string and span (Windows-only).
- Added Darwin-specific API for querying resource forks (akin to trailing separators).
- Added `FilePath.init(anchor:_:hasTrailingSeparator:)` and expounded on path decomposition and reconstitution.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [April 21, 2026, 3:40pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/12 "2026-04-21T15:40:32Z")

</div>

~~Swift Testing cannot use `Span` directly or indirectly, so unsafe pointers are still necessary for us to adopt.~~

The above only applies on Darwin, where we don't potentially need a dependency on `FilePath` at this time. Ignore me!

---

<div class="post-metadata">

**Author:** ![3405691582](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/3405691582/32/10696_2.png) [@3405691582](https://forums.swift.org/u/3405691582)\
**Post date:** [April 21, 2026, 5:30pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/13 "2026-04-21T17:30:07Z")

</div>

What does the right way to unsafèdly convert the Span into a C string look like?

---

<div class="post-metadata">

**Author:** ![glessard](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glessard/32/409_2.png) [@glessard](https://forums.swift.org/u/glessard)\
**Post date:** [April 22, 2026, 6:31pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/14 "2026-04-22T18:31:41Z")

</div>

For now, that would be

```swift
nullTerminatedCodeUnits.withUnsafeBufferPointer {
    let cStringPointer = $0.baseAddress
    return myCFunction(cStringPointer)
}

```

(strlen will return `($0.count-2)`).

Note that this is not the final answer. We are interested in investigating linear buffers coded by their terminating element (`0` for a C string,) as well as a family of interop-only non-escapable pointer wrappers that would move safe C-interop out of closures.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [April 23, 2026, 5:50pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/15 "2026-04-23T17:50:06Z")

</div>

Given that a _very_ common use case for `FilePath` is interacting with platform-specific C I/O API, we probably _do_ want `withCString` or similar.

---

<div class="post-metadata">

**Author:** ![glessard](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glessard/32/409_2.png) [@glessard](https://forums.swift.org/u/glessard)\
**Post date:** [April 23, 2026, 6:01pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/16 "2026-04-23T18:01:12Z")

</div>

We would like to stop adding C-interop API to specific types; do you think that is a bad goal?

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [April 23, 2026, 6:50pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/17 "2026-04-23T18:50:42Z")

</div>

I think it's a great goal for Swift code to always be able to pass around local file paths as `FilePath`s. However, most path manipulation is ultimately in service of creating a path that can be passed off to some OS API, and if there's no standard way for arbitrary code to actually do that without writing its own copy-into-a-buffer code, that seems to _undermine_ that goal rather than support it. Presumably we will eventually have a batteries-included local I/O library that just works with `FilePath`, but we don't have that now, and even when we do, it won't wrap every OS API that takes a path, much less every third-party C API. I think not having a convenient way to get a `const char *` / `LPCWSTR` / whatever out of this API would be a mistake.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [April 23, 2026, 11:44pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/18 "2026-04-23T23:44:06Z")

</div>

Hmm, I just noticed that this discussion is happening in the pitch thread, not the [currently active review thread](https://forums.swift.org/t/se-0529-add-filepath-to-the-standard-library/86194). I'm going to copy my post over there and close this thread; please continue any discussion over there.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [April 23, 2026, 11:44pm UTC](https://forums.swift.org/t/pitch-2-add-filepath-to-stdlib/85695/19 "2026-04-23T23:44:09Z")

</div>


