Skip to content
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

Make Body.data generic #534

Merged
merged 1 commit into from Jan 13, 2022

Conversation

karwa
Copy link
Contributor

@karwa karwa commented Dec 19, 2021

I don't think there is a need for this specific API to use Foundation.Data -- we can broaden it to all RandomAccessCollections . RAC seems like the most appropriate constraint given the up-front count calculation.

This removes a Foundation dependency, and should be source-compatible.

@dnadoba
Copy link
Collaborator

dnadoba commented Dec 20, 2021

Sadly this is a source breaking change because we can create an unapplied reference to this method e.g.:

let makeBodyFromData = HTTPClient.Body.data

After your change this no longer compiles with the error message "Generic parameter 'Bytes' could not be inferred".

What we can do instead is leaving the old method signature as is and adding your new method as an additional overload.

@karwa karwa force-pushed the this-is-a-generic-branch-name branch 2 times, most recently from ed5ae39 to 09394d9 Compare January 10, 2022 16:35
@karwa
Copy link
Contributor Author

karwa commented Jan 10, 2022

@dnadoba Okay, I've added the Data version back as you suggested. It's a little awkward, but the idea is that it forwards to the generic version to avoid duplicating implementations.

I've also added a test to make double-sure that unapplied references to HTTPClient.Body.data continues to resolve to the Data version.

Copy link
Collaborator

@dnadoba dnadoba left a comment

Choose a reason for hiding this comment

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

Thanks a lot, great patch! @fabianfett WDYT?

/// - parameters:
/// - bytes: Body `Data` representation.
public static func data(_ bytes: Data) -> HTTPClient.Body {
func forwardToGenericImpl<C>(_ value: C) -> HTTPClient.Body where C: RandomAccessCollection, C.Element == UInt8 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

@Lukasa do you know if the compiler will specialise this local function?

Copy link
Contributor Author

@karwa karwa Jan 10, 2022

Choose a reason for hiding this comment

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

It appears to: https://swift.godbolt.org/z/WKeeG5r7v

Note that both test and doSomething just compare to 99, without calling the generic function. This function should be equivalent to the concrete version of doSomething.

Copy link
Collaborator

Choose a reason for hiding this comment

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

As @karwa says, yes, the compiler should absolutely specialise this function. However, it's a pretty ugly thunk to have to have, so I'd like to ask whether we can differentiate between this method and the other method called data by renaming the other one. That way we don't need to write this thunk out explicitly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, well the async API seems to use bytes for this. So we could use that.

I went with data to try and remove the Foundation.Data dependency whilst still supporting Data. But if we have to add the extension for source compatibility, that reasoning isn't quite as strong. Then again, there is value in having the same thing be spelled the same way, and it's the API we have, so... ⚖️ . The thunk is not going to be winning any beauty awards, for sure, but is it less ugly than having two spellings for essentially the same operation? I'm not sure.

If you really think it's worth it, I could rename it to bytes.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In general I'm disinclined to rely on type-based method overloads. We've had a bunch of problems with this in the past where having methods whose name is the same that differ only based on type leans excessively heavily on the type checker. If these differed only on return value I'd outright refuse to accept them having the same name: differing based on argument type is less bad, but in this instance I think I'd still rather use a different name. There's existing prior art in NIO for using the word data in method names to mean "accepts/returns Foundation.Data" and bytes to mean "accepts/returns something else", so I think we're in good company here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, I wasn't aware that pattern was used elsewhere in NIO. I've changed it to .bytes now.

@karwa karwa force-pushed the this-is-a-generic-branch-name branch from 09394d9 to afaa340 Compare January 13, 2022 12:28
@karwa karwa requested a review from Lukasa January 13, 2022 12:33
Copy link
Collaborator

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

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

One tiny nit and then we're good.

/// - parameters:
/// - bytes: Body `Data` representation.
public static func data(_ data: Data) -> HTTPClient.Body {
return bytes(data)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I know this is a ridiculous nit, but:

Suggested change
return bytes(data)
return self.bytes(data)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@karwa karwa force-pushed the this-is-a-generic-branch-name branch from afaa340 to cbb8fa8 Compare January 13, 2022 13:48
@Lukasa Lukasa merged commit 6474d8d into swift-server:main Jan 13, 2022
@karwa karwa deleted the this-is-a-generic-branch-name branch January 13, 2022 15:29
@fabianfett fabianfett added the 🔼 needs-minor-version-bump For PRs that when merged cause a bump of the minor version, ie. 1.x.0 -> 1.(x+1).0 label Jan 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔼 needs-minor-version-bump For PRs that when merged cause a bump of the minor version, ie. 1.x.0 -> 1.(x+1).0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants