Skip to content

fix build on Xcode 13 RC #78

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

Conversation

diederich
Copy link

This fixes the build of PathKit on Xcode 13 RC.

strdup returns an implicitly unwrapped optional, which seems to loose its "implicit" via the assignment.
I couldn't find anything in the Xcode release notes, but I guess it's a fair change :-)
Let's treat the returned pointers as true optionals and instead of crashing, return defaults.

`strdup` returns an implicitly unwrapped optional,
which seems to loose its "implicit" via the assignment.
I couldn't find anything in the release docs, but I guess it's a fair
change :-)
Let's use them as proper optionals and instead of crashing, return defaults.
Copy link
Owner

@kylef kylef left a comment

Choose a reason for hiding this comment

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

The reasons that strdup will return NULL are when insufficient memory is available.

RETURN VALUE
On success, the strdup() function returns a pointer to the duplicated string. It returns
NULL if insufficient memory was available, with errno set to indicate the error.

I would imagine that in the past Swift would have caused a crash in this case, the change to the compiler exposes strdups error case to to caller. I'd suggest we retain the existing behaviour because silently handling errors and returning false information is unexpected behaviour.

@@ -587,8 +587,8 @@ extension Path {

extension Path {
public static func glob(_ pattern: String) -> [Path] {
guard let cPattern = strdup(pattern) else { return [] }
Copy link
Owner

Choose a reason for hiding this comment

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

Returning an empty array here is perhaps undesired as from the callers perspective, they will believe that the glob operation showed there have been no matched files. Which is not necessarily the case, we instead failed to load them.

@@ -619,8 +619,7 @@ extension Path {
}

public func match(_ pattern: String) -> Bool {
let cPattern = strdup(pattern)
let cPath = strdup(path)
guard let cPattern = strdup(pattern), let cPath = strdup(path) else { return false }
Copy link
Owner

Choose a reason for hiding this comment

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

Returning false here represents to the caller that the pattern did not match, which may not be true.

@diederich
Copy link
Author

The reasons that strdup will return NULL are when insufficient memory is available.

Right right, the return value has always been an implicitly unwrapped optional.

[snip]

I would imagine that in the past Swift would have caused a crash in this case, the change to the compiler exposes strdups error case to to caller.

Did a bit more reading, and it's actually one of the examples from https://swift.org/blog/iuo/
While the return value carried the "!", it gets lost in the assignment in the next step:
let notAnImplicitOptions = somethingThatReturnsAnImplicitOptional()

So either a bug was fixed that this now works as expected, or free changed in that it took an optional before (which would also be fair I guess, given in C a free(0) is also fine )

​I'd suggest we retain the existing behaviour because silently handling errors and returning false information is unexpected behaviour.

Fair, thanks for the feedback. Happy to put up a change!

It feels like a preconditionFailure isn't the right call, given it's not really a programmer error. Would you wanna change the signature to return optionals / throw, or just hard crash with the a force unpack?

@kylebrowning
Copy link

I dont know if this is worse but in my PR I just safely unwrapped them to free them, given that if they come back as nil, they probably were already freed?

@diederich
Copy link
Author

I dont know if this is worse but in my PR I just safely unwrapped them to free them, given that if they come back as nil, they probably were already freed?

My hunch is it would crash a few lines down.
e.g. fnmatch gets imported into Swift as:
public func fnmatch(_: UnsafePointer<CChar>!, _: UnsafePointer<CChar>!, _: Int32) -> Int32

So my hunch is it would just crash there then :-/

@hiltonc
Copy link

hiltonc commented Sep 20, 2021

It seems like we're blocked here but it's not clear to me what the next steps are.

@kylef
Copy link
Owner

kylef commented Sep 20, 2021

@diederich what about somthing like this:

guard let ... = strdup(...) else {
  fatalError("strdup returned null: Likely out of memory")
}

Potentially message can contain string interpolation for the errno if that's exposed.

@chrisballinger chrisballinger mentioned this pull request Sep 22, 2021
@chrisballinger
Copy link
Contributor

Implemented some of that feedback over here: #80

@diederich
Copy link
Author

#80 LGTM! Thanks @chrisballinger 🙏
Closing this..

@diederich diederich closed this Sep 22, 2021
@diederich diederich deleted the feature/fix-build-Xcode-13-RC branch September 22, 2021 09:35
@diederich diederich restored the feature/fix-build-Xcode-13-RC branch September 22, 2021 09: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.

5 participants