Skip to content

Only use FoundationEssentials if available #749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

t089
Copy link

@t089 t089 commented Mar 25, 2025

This is a new attempt similar to #674 to only use FoundationEssentials if it is available. It should address #748.

To enable the usage of only FoundationEssentials some API usage was replaced with either API from the StdLib (eg. replaceOccurances -> replace).

Instead of using range(_) method, we use the _range(_) method pulled from swift-foundation itself.

However, to make Mutex<T> work without NSLock, I pulled in NIOLock from swift-nio. Unfortunately, I did not find a nice way to make it work with Synchronization.Mutex instead.

Tests pass on swift 5.7 to 6.0 on linux.

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this, @t089! A couple notes below – I'll look at getting rid of the lock implementation altogether in a different PR.

Comment on lines +206 to +213
#if canImport(FoundationEssentials)
func shellEscapeForSingleQuotedString(iterationCount: UInt64 = 1) -> Self {
iterationCount == 0
? self
: replacing("'", with: "'\\''")
.shellEscapeForSingleQuotedString(iterationCount: iterationCount - 1)
}
#else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this canImport check necessary? replacing(_:with:) comes from the Swift standard library (via _StringProcessing), not FoundationEssentials. We may be able to do away with the other branch on these altogether.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for all the branches where the result is the same, we should remove the conditional code and use the stdlib version theres no need to use the variants from Foundation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is the stdlib version. On macOS this is only available on newer macOS versions. But since on macOS you anyhow have foundation I chose this route.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd personally prefer manually backdeploying these stdlib functions then.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rauhul Should I try to copy an implementation from _StringProcessing? Alternatively, is there something like #if canImport(SwiftStdlib, 6.0) that we could use here?

if let optionsRange = name.range(of: "_options"),
if let optionsRange = name._range(of: "_options"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try firstRange(of:) here for the non-Foundation version, instead of copying in an implementation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'firstRange(of:)' is only available in macOS 13.0 or newer

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@natecook1000 what is your preferred course of action? Keep the copied implementation here?

/// of lock is safe to use with `libpthread`-based threading models, such as the
/// one used by NIO. On Windows, the lock is based on the substantially similar
/// `SRWLOCK` type.
public struct NIOLock {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't love bringing this in, especially as we barely need a lock. (It's used to manage an environment variable we only want to set when processing custom completions.) There's a standard library atomic-swap-based lock that we could use instead; I'll look at making that change until we can switch to using Synchronization.Mutex.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! Happy to revert this!

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.

3 participants