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

Update simd-json to make serenity compile again #2536

Closed
wants to merge 4 commits into from

Conversation

kangalio
Copy link
Collaborator

@kangalio kangalio commented Sep 12, 2023

And fix an unsoundness (lol)

I found out that serenity doesn't compile with the simd_json feature in poise https://github.com/serenity-rs/poise/actions/runs/6158123854/job/16710276804

@kangalio
Copy link
Collaborator Author

After reading #2474 (comment), I realize serenity actually re-exports the raw serialization and deserialization functions from the underlying JSON library in serenity::json::prelude. As such, any upgrade to serde-json or simd-json is a breaking change >:(

We could hack around this unfortunate decision by replacing the re-exported simd_json::from_str with a custom impl that keeps the old signature (at the cost of a soundness hole, that probably no one ever will encounter because this is such a niche serenity API). We should also maybe deprecate the re-exports from the underlying JSON libraries?

@mkrasnitski
Copy link
Collaborator

Is changing the trait bound to DeserializeOwned a breaking change? I'm not sure - since we're dealing with JSON, are there any types that don't implement DeserializeOwned?

@kangalio
Copy link
Collaborator Author

serenity::json::from_str isn't public API! Only serenity::json::prelude::from_str is. The two differ in that the public one is directly re-exported from serde_json or simd_json, whereas the private one is a wrapper function around serde_json or simd_json


I have another hack idea to fix the semver issue: depend on both simd_json 0.4 and 0.10 - use 0.10 internally, re-export 0.4. It's silly but it's a silly solution to a silly problem (namely, serenity publicly re-exporting implementation details)

@arqunis arqunis added enhancement An improvement to Serenity. dependencies Related to Serenity dependencies. labels Sep 12, 2023
src/json.rs Outdated Show resolved Hide resolved
Comment on lines +75 to +78
// Have to clone the argument because simd_json mutates the argument
// And we can't just take &mut str either because simd_json mutates the string such that it may
// not be UTF-8 afterwards, which is unsound
Ok(simd_json::from_slice(&mut s.as_bytes().to_vec())?)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does from_slice work with multi-byte characters? I think that passing in a &mut s.to_string() would still be fine here, since even if the string becomes invalid UTF-8, it gets dropped immediately afterward.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Does from_slice work with multi-byte characters?

Yes:
Screenshot_20230919_033925

I think that passing in a &mut s.to_string() would still be fine here, since even if the string becomes invalid UTF-8, it gets dropped immediately afterward.

I originally thought the mere existence of a non UTF-8 str is instant UB but I looked it up and it seems you're right

Still, that would need an unsafe block. Using from_slice needs no unsafe block and has no performance penalty (I expect?

As per arqunis' / acdenis' request.

Also add a feature gated compile_error! to make sure people don't accidentally enable simd-json instead of simd_json again
@github-actions github-actions bot added ci Related to the continuous integration. model Related to the `model` module. labels Sep 19, 2023
@mkrasnitski
Copy link
Collaborator

Ok, turns out this approach doesn't entirely work because having things like OwnedValue and Object imported from simd-json 0.10 is not compatible with methods like to_string which are imported from 0.4. What would need to happen is for two separate preludes to be created, one which is pub that re-exports everything from 0.4, and one which is internal containing everything from 0.10. Additionally, the pub types like Value, JsonMap, JsonError, etc. would need to be set to their versions from simd_json_old, which means that their new versions should therefore also be exported only in the "internal-only" prelude.

Considering that the json macro is broken on old simd-json versions, I'm really not sure if it's worth fixing this just to re-export a broken API, because the later rebases of next on top of that work would be pretty painful. Maybe we just bite the bullet and re-export the new versions of the functions, except for from_str for which the wrapper is already pub anyways? I don't think any of the other function signatures have been broken by simd-json.

The other fixes in this PR (like the feature flag typo fix) are fine and can be left in.

@mkrasnitski
Copy link
Collaborator

Any updates on this?

@kangalio
Copy link
Collaborator Author

I'm currently not motivated to implement that separate prelude thing, and pushing breaking changes into current feels wrong to me. Maybe it's ok if I just close this PR, let simd-json continue to be broken on current, and wait for next instead ™ ?

@mkrasnitski
Copy link
Collaborator

If you'd like, we can close this and split it into separate PRs.

@kangalio
Copy link
Collaborator Author

Split into what PRs? What would they do?

@mkrasnitski
Copy link
Collaborator

Replacing the uses of the incorrect simd-json feature with simd_json is relatively simple and worth incorporating.

@kangalio
Copy link
Collaborator Author

More trouble than its worth tbh. That replacing is a "pick up a piece of litter in your way" level of change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci Related to the continuous integration. dependencies Related to Serenity dependencies. enhancement An improvement to Serenity. model Related to the `model` module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants