-
Notifications
You must be signed in to change notification settings - Fork 569
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
Add a no_std/alloc feature #606
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This is so much easier to review than the earlier no_std attempts. I intend to dedicate time toward getting this reviewed and merged.
I have not looked at most of this yet but here are some initial comments:
|
||
# Provide integration for heap-allocated collections without depending on the | ||
# rest of the Rust standard library. | ||
# NOTE: Disabling both `std` *and* `alloc` features is not supported yet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please find a way to produce a reasonable error message for this case. The current error if you do serde_json = { default-features = false }
is >1500 lines which is insane.
https://github.com/dtolnay/syn/blob/1.0.14/tests/features/mod.rs + https://github.com/dtolnay/syn/blob/1.0.14/tests/features/error.rs shows one good way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that's neat! I wanted to do so but couldn't think of a reliable way to only show one compilation error.
As written here, maybe it'd be good to just support std
and no-std
(implying using alloc
)? This would mean we wouldn't have to care about detecting no std
and alloc
anymore.
EDIT: Nevermind, we still need the Cargo alloc
feature for serde/alloc
and thus we still must check for either std
or alloc
to be enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 7852d2f.
Is there a way to run trybuild with custom feature flags, like compiletest? It'd be quite handy to have a UI test for --no-default-features
so that we can catch whenever the error message regresses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current error if you do
serde_json = { default-features = false }
[...]
Shouldn't this new error be considered a breaking change?
src/lib.rs
Outdated
pub use self::core::marker::{self, PhantomData}; | ||
pub use self::core::result::{self, Result}; | ||
|
||
#[cfg(all(feature = "alloc", not(feature = "std")))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplified to not(feature = "std")
because we know alloc must be enabled in that case. Same thing below.
In general feature = "alloc"
should not need to appear anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did that to introduce distinction between std
, alloc
and no feature at all, but maybe it'd be good only introduce two: default std
and no-std
(which implies alloc
and is supported from 1.36 onwards)...
I'll adapt the code accordingly, thanks!
@@ -365,6 +427,7 @@ pub mod map; | |||
pub mod ser; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From cargo doc --no-default-features --features alloc
:
This seems bad because the following would be accepted in alloc mode and break if a different part of the dependency graph enables std mode.
struct S;
impl serde_json::ser::Formatter for S {
fn write_null<W: ?Sized>(&mut self, _: &mut W) -> Result<(), &'static str> {
Err("")
}
}
Either Formatter needs to be removed from the public API in alloc mode or the error type needs to be changed to an opaque type with no more than a subset of io::Error's API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I didn't notice that, thanks!
Since std::io::Result
is part of the default, public API I don't think we can be backwards compatible (methods are one thing but sth may depend on it being explicitly this type from std
IIUC).
Because of this, I think the only thing we can do now, until std::io
somehow lands in core
, is to hide this from public API in no-std
case.
EDIT: Again, sorry for the noise. You're right, that's a concern about code written for core not being compatible with std (not being a subset of real io) rather than the concrete public API... I'm on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reimplemented a small subset of std::io::Error
and friends so that accidentally opting into std
should not break stuff
I addressed the feedback and thus also managed to unify the
Overall, I'm pretty happy with how the |
Inlining this simple, already `core`-compatible function is better than noisily repeating the same definition that does exactly the same, albeit hidden behind a fn call.
So that when implementing a no-`std` logic we don't break the build when some other dependency opts into `std` (causing API mismatch).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks great to me. I am making some tweaks in later commits but this is ready to land.
Question: for your use case do you require to_writer and/or Serializer, or only to_string? I am removing to_writer and Serializer from the public API in no-std mode for now. These rely on the caller to pass a Write impl and the only impl this PR provides in serde_json is for Vec<u8>. It is going to require more design work to figure out how best to expose that. With the io facade as implemented here, the caller is unable to write Write impls, and I also don't want to be in the business of copying many more Write impls from std into serde_json.
Awesome, thank you!
I think
That's completely understandable! It's worth noting that for the second iteration of
Thanks for not blocking on this but it'd be completely fine to ask me to follow up with other tweaks related to this PR! |
Published in 1.0.45. |
Relevant Serde PR: serde-rs/serde#1620 To support both no-/std builds without using somewhat noisy conditional compilation directives, we implement the re-exported `serde::de::StdError` trait in serde-rs#606. However, this was only introduced in >= 1.0.100, so we need to bump the version requirement of serde. On the off chance of someone pulling in incompatible 1.0.4{5,6} versions of serde_json, I believe it'd be good to yank those and cut a new release with this patch. Sorry for the omission in the original PR. Fixes serde-rs#621.
Relevant Serde PR: serde-rs/serde#1620 To support both no-/std builds without using somewhat noisy conditional compilation directives, we implement the re-exported `serde::de::StdError` trait in serde-rs#606. However, this was only introduced in >= 1.0.100, so we need to bump the version requirement of serde. On the off chance of someone pulling in incompatible 1.0.4{5,6} versions of serde_json, I believe it'd be good to yank those and cut a new release with this patch. Sorry for the omission in the original PR. Fixes serde-rs#621.
Relevant Serde PR: serde-rs/serde#1620 To support both no-/std builds without using somewhat noisy conditional compilation directives, we implement the re-exported `serde::de::StdError` trait in serde-rs#606. However, this was only introduced in >= 1.0.100, so we need to bump the version requirement of serde. On the off chance of someone pulling in incompatible 1.0.4{5,6} versions of serde_json, I believe it'd be good to yank those and cut a new release with this patch. Sorry for the omission in the original PR. Fixes serde-rs#612.
This builds up on #588 (thanks @Freax13!).
With this, we support
no_std
withalloc
crate, starting from Rust 1.36 (this was done so that we can use it in WebAssembly environment but any such environment will work).To minimize the noise, I tried to use the facade approach already used in Serde to provide some consistency between the two and improved on the
io
facade to work around it missing incore
.Thanks in advance for taking your time to review this and let me know if I can improve anything to help this land!
Closes #588. Closes #516.