Skip to content

Avoid utf8CString when when owned storage is not required#1829

Merged
jmschonfeld merged 2 commits intoswiftlang:mainfrom
jmschonfeld:avoid-owned-cstring
Mar 24, 2026
Merged

Avoid utf8CString when when owned storage is not required#1829
jmschonfeld merged 2 commits intoswiftlang:mainfrom
jmschonfeld:avoid-owned-cstring

Conversation

@jmschonfeld
Copy link
Copy Markdown
Contributor

Avoids calling utf8CString when not necessary

Motivation:

I noticed we use String.utf8CString in a handful of places in Foundation. Since this property returns a ContiguousArray<CChar> which is an owned type, it must copy the contents of the string into an array. Instead, we can use withCString which provides the same functionality, but can avoid a copy if the String already contains null terminated UTF-8 (which native strings do). Additionally, in some cases, we didn't actually need a null terminated string and we can use withUTF8 instead which also avoids copying when the String contains non-null terminated UTF-8 (which some bridged strings do as well). This should avoid copying these strings each time (when not required)

Modifications:

Replace uses of utf8CString with withCString/withUTF8

Result:

Copies are avoided when the string can provide access to an inner cstring or utf8 pointer

Testing:

Existing tests cover these modified functions

@jmschonfeld jmschonfeld requested a review from a team as a code owner March 18, 2026 19:38
@jmschonfeld
Copy link
Copy Markdown
Contributor Author

@swift-ci please test

@kperryua
Copy link
Copy Markdown
Contributor

Looks like more of the C function pointer nullability mismatch.

@jmschonfeld
Copy link
Copy Markdown
Contributor Author

cannot convert value of type 'UnsafePointer<UInt8>' to expected argument type 'UnsafePointer<CChar>?' (aka 'Optional<UnsafePointer<Int8>>') because var 'ucasemap_utf8ToLower' was not imported from C header

Well, this is quite strange because ucasemap_utf8ToLower certainly is imported from a C header. I suspect that this has something to do with the macro aliasing feature. @compnerd @xedin similar to the attribute that we were missing to declare these aliases had no storage (to silence concurrency warnings), are we also missing some attribute on the imported decl to declare that it came from a C header so that these types of mappings are allowed?

@compnerd
Copy link
Copy Markdown
Member

@jmschonfeld no, I don't think that this conversion is allowed. This is an issue related to -fsigned-char vs -funsigned-char.

@jmschonfeld
Copy link
Copy Markdown
Contributor Author

@jmschonfeld no, I don't think that this conversion is allowed. This is an issue related to -fsigned-char vs -funsigned-char.

Given that macOS CI passed, this conversion must be allowed in some situations and the only difference in this function between macOS and Linux/Windows etc. is the symbol renaming I believe (which is disabled on macOS)

@jmschonfeld
Copy link
Copy Markdown
Contributor Author

@jmschonfeld no, I don't think that this conversion is allowed. This is an issue related to -fsigned-char vs -funsigned-char.

Given that macOS CI passed, this conversion must be allowed in some situations and the only difference in this function between macOS and Linux/Windows etc. is the symbol renaming I believe (which is disabled on macOS)

Oh sorry I misunderstood. Yeah it looks like even building on macOS with the symbol renaming enabled it builds successfully, so sounds like it's a platform difference between the value of what CChar is based on those build flags you mentioned?

@jmschonfeld
Copy link
Copy Markdown
Contributor Author

@swift-ci please test

1 similar comment
@jmschonfeld
Copy link
Copy Markdown
Contributor Author

@swift-ci please test

@compnerd
Copy link
Copy Markdown
Member

compnerd commented Mar 20, 2026

@jmschonfeld no, I don't think that this conversion is allowed. This is an issue related to -fsigned-char vs -funsigned-char.

Given that macOS CI passed, this conversion must be allowed in some situations and the only difference in this function between macOS and Linux/Windows etc. is the symbol renaming I believe (which is disabled on macOS)

Oh sorry I misunderstood. Yeah it looks like even building on macOS with the symbol renaming enabled it builds successfully, so sounds like it's a platform difference between the value of what CChar is based on those build flags you mentioned?

It isn't flag related, it is the platform ABI. Windows and Darwin disagree on what a char should be.

@jmschonfeld jmschonfeld force-pushed the avoid-owned-cstring branch from 93e9e87 to 9085110 Compare March 20, 2026 17:53
@jmschonfeld
Copy link
Copy Markdown
Contributor Author

@swift-ci please test

1 similar comment
@jmschonfeld
Copy link
Copy Markdown
Contributor Author

@swift-ci please test

@jmschonfeld jmschonfeld merged commit c056602 into swiftlang:main Mar 24, 2026
22 checks passed
@jmschonfeld jmschonfeld deleted the avoid-owned-cstring branch March 24, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants