-
Notifications
You must be signed in to change notification settings - Fork 37
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
#derive (Pread) requires From<u8> for arrays? #107
Comments
This should work; seems like a bug, iiuc? We have a test for array with generic value, but that value only appears to be u8's: scroll/scroll_derive/tests/tests.rs Lines 179 to 196 in f711272
|
Yea can repro with this diff --git a/scroll_derive/tests/tests.rs b/scroll_derive/tests/tests.rs
index 14dec4e..f04268f 100644
--- a/scroll_derive/tests/tests.rs
+++ b/scroll_derive/tests/tests.rs
@@ -269,3 +269,15 @@ fn test_custom_ctx_derive() {
};
assert_eq!(data3, bytes.ioread_with(LE).unwrap());
}
+
+#[derive(Debug, Pread, Pwrite, SizeWith)]
+struct Data12 {
+ ids: [Data11; 1],
+}
+
+#[test]
+fn test_array_with_pread_data() {
+ let bytes = [0xde, 0xed, 0xef, 0x10, 0x10, 0x01];
+ let data: Data12 = bytes.pread_with(0, LE).unwrap();
+ assert_eq!(data.ids[0].a, 0xedde);
+} |
@Systemcluster i see ea70080 added the generics support in the derive, and there's been some additional work by @Easyoakland on the derive side, I think this is probably just not correct implemented for nested types in arrays. |
The bug on the derive side is here: impl<'a> ::scroll::ctx::TryFromCtx<'a, ::scroll::Endian> for Data12
where
Data12: 'a,
{
type Error = ::scroll::Error;
#[inline]
fn try_from_ctx(
src: &'a [u8],
ctx: ::scroll::Endian,
) -> ::scroll::export::result::Result<(Self, usize), Self::Error> {
use ::scroll::Pread;
let offset = &mut 0;
let data = Self {
ids: {
let mut __tmp: [Data11; 1] = [0u8.into(); 1usize];
src.gread_inout_with(offset, &mut __tmp, ctx)?;
__tmp
},
};
Ok((data, *offset))
}
} right here: let mut __tmp: [Data11; 1] = [0u8.into(); 1usize]; We have a safe and sound array impl in rust using impl<'a> ::scroll::ctx::TryFromCtx<'a, ::scroll::Endian> for Data12
where
Data12: 'a,
{
type Error = ::scroll::Error;
#[inline]
fn try_from_ctx(
src: &'a [u8],
ctx: ::scroll::Endian,
) -> ::scroll::export::result::Result<(Self, usize), Self::Error> {
use ::scroll::Pread;
let offset = &mut 0;
let data = Self {
ids: src.gread_with(offset, ctx)?,
};
Ok((data, *offset))
}
} Historically, I think the derive with arrays significantly predated existence of MaybeUninit, and it working with any arrays, and it never came up, so I think I probably just stuck |
cread with also broken in same manner: scroll/scroll_derive/src/lib.rs Lines 434 to 438 in f711272
unfortunately, something like: diff --git a/scroll_derive/src/lib.rs b/scroll_derive/src/lib.rs
index a5714dd..846e356 100644
--- a/scroll_derive/src/lib.rs
+++ b/scroll_derive/src/lib.rs
@@ -14,18 +14,6 @@ fn impl_field(
let default_ctx = syn::Ident::new("ctx", proc_macro2::Span::call_site()).into_token_stream();
let ctx = custom_ctx.unwrap_or(&default_ctx);
match *ty {
- syn::Type::Array(ref array) => match array.len {
- syn::Expr::Lit(syn::ExprLit {
- lit: syn::Lit::Int(ref int),
- ..
- }) => {
- let size = int.base10_parse::<usize>().unwrap();
- quote! {
- #ident: { let mut __tmp: #ty = [0u8.into(); #size]; src.gread_inout_with(offset, &mut __tmp, #ctx)?; __tmp }
- }
- }
- _ => panic!("Pread derive with bad array constexpr"),
- },
syn::Type::Group(ref group) => impl_field(ident, &group.elem, custom_ctx),
_ => {
quote! { while it fixes the issue for non-generic structs, it unfortunately is broken for generics, seems like the error type diverges?
i think there is probably an easy fix, but it's not hitting me at the moment and i didn't add the generics part so somewhat unsure about those code paths :) |
I have a patch fixing this but: impl<'a, T, Y> ::scroll::ctx::TryFromCtx<'a, ::scroll::Endian> for Data8<T, Y>
where
T: ::scroll::ctx::TryFromCtx<'a, ::scroll::Endian, Error = ::scroll::Error>
+ ::std::marker::Copy, I don't like how the T error is fixed to ids: src
.gread_with::<[T; 3]>(offset, ctx)
.map_err(::scroll::Error::from)?, on all the greads but it doesn't like this., with this (to my mind, very odd) error message:
unsure why it thinks |
tl;dr we can do generics and fix this bug but it makes the generic type require it's error at the moment to be |
@joschock if possible, would you mind testing this branch to see if it fixes issues for you? |
unfortunately this wouldn't be a minor patch release since in theory it changes the generics parameters for the generics portion of derive. I could make it a patch release by preserving the same broken behavior that presumably no one is using. alternatively I could just take the risk and push it as a minor patch since i can't imagine anyone was relying on generic bounds from scroll requiring their generic type be |
For anyone passively reading this and wondering wtf i'm talking about, e.g., this code compiled before in our tests: #[derive(Debug, PartialEq, Eq, Pread, Pwrite, IOread, IOwrite, SizeWith)]
#[repr(C)]
struct Data8<T, Y> {
ids: [T; 3],
xyz: Y,
}
#[test]
fn test_generics() {
let mut bytes = [0xde, 0xed, 0xef, 0x10, 0x10];
let data: Data8<u8, u16> = bytes.pread_with(0, LE).unwrap();
assert_eq!(data.ids, [0xde, 0xed, 0xef]);
assert_eq!(data.xyz, 0x1010); so one might wonder how was And indeed, in the code above, Whew 😅 I think on hindsight it's probably safe to remove this bound in a minor patch, because while it's technically breaking, no one could really have relied on the behavior realistically, though it's possible if they have hyper generic code they may have had to forward that bound, but in this case, removing the bound won't break them, it's just one less thing we require the generic T to implement. |
@m4b - fast turnaround 🥇 Yes, the above PR branch makes it work without requiring the unexpected |
ok it's merged into master/main; @joschock do you mind waiting a bit, I'd like to understand how best to fix the similarly identical bug in cread derive; i may end up just emitting derive error that it doesn't work on fixed size arrays, but today the cread implementation (similar to pread) is broken on multiple levels; adding the From impl just lets it compile; if you were to pread it out of real data after pwriting, roundtripping would fail, e.g,. it doesn't work at all :D |
(waiting a bit for a crates release that is) |
@m4b, no rush on my end; I'll just peg to the merge commit for the interim. |
Perhaps I'm not understanding some elements of scroll_derive and using it wrong, but the following won't compile:
the error is:
Adding a
From<u8>
impl onB
does allow it to compile, but that seems like maybe not the right thing to do, since there isn't an actual real conversion from u8?Is there something I should do differently here to make this work as expected?
The text was updated successfully, but these errors were encountered: