The reported error is this:
\n// error[E0597]: `bytes` does not live long enough\nfn print_header(bytes: Vec<u8>) -> Result<()> {\n// ----- binding `bytes` declared here\n let hdr = Header::ref_from_bytes(&bytes)?;\n// -----------------------^^^^^^-\n// | |\n// | borrowed value does not live long enough\n// argument requires that `bytes` is borrowed for `'static`\n println!(\"{:#?}\", hdr);\n Ok(())\n}\n//- `bytes` dropped here while still borrowedI found that rather puzzling, but I am far from experienced with rust, so that's not unusual.
\nRequiring the value to be parsed to be 'static seems like it would make the library extremely difficult to use in a real-world application.
If you were to change the function definition to expect a &[u8] instead of Vec<u8> the error changes:
// error[E0521]: borrowed data escapes outside of function\nfn print_header(bytes: &[u8]) -> Result<()> {\n// ----- - let's call the lifetime of this reference `'1`\n// |\n// `bytes` is a reference that is only valid in the function body\n let hdr = Header::ref_from_bytes(&bytes)?;\n// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n// |\n// `bytes` escapes the function body here\n// argument requires that `'1` must outlive `'static`\n println!(\"{:#?}\", hdr);This error is more useful. How does bytes escape the function body there?
Of course, it is the ? operator. anyhow requires error types to be 'static and zerocopy includes the reference to be parsed in the error value. So the compiler forces the input bytes to be 'static in case of the Err() outcome.
I believe this is very similar to (if not the same as) the issue described here: #2262
\nSo the problem can be resolved by switching the line:
\nlet hdr = Header::ref_from_bytes(&bytes)?;to either
\nlet hdr = Header::ref_from_bytes(&bytes).unwrap();or
\nlet hdr = Header::ref_from_bytes(&bytes)\n .map_err(|_| format_err!(\"ref_from_bytes failed\"))?;And in that linked discussion, in addition to other changes, the user also switches ? to .unwrap(). They don't mention use of anyhow specifically in that discussion however.
I'm not really sure what my question is.
\nIs this issue something that an experienced rust developer would immediately recognize and fix? Or is this awkward ergonomics that might be worth looking into?
I have no problem just mapping the error to something else, but thought I'd raise the issue just in case there was a better solution.
","upvoteCount":1,"answerCount":1,"acceptedAnswer":{"@type":"Answer","text":"It's anyhow that imposes the 'static requirement, since — under the hood — anyhow Boxes up (and type erases) the error value. The requirement specifically comes from this conversion, which is implicitly invoked by ?.
The correct solution is, yes, to map zerocopy's error to something else that meets these requirements. We're lightly looking into providing an API that would make this easier, but it's not on our near-term roadmap right now.
","upvoteCount":1,"url":"https://github.com/google/zerocopy/discussions/2498#discussioncomment-12845335"}}}-
|
This code does not compile, but it seems to me that it should. use zerocopy::*; // 0.8.24
use anyhow::{format_err, Result}; // 1.0.97
#[derive(Debug, FromBytes, Immutable, Unaligned, KnownLayout)]
#[repr(C, packed)]
struct Header {
version: u8
}
fn main() {
print_header(vec![1_u8]).unwrap();
}
fn print_header(bytes: Vec<u8>) -> Result<()> {
let hdr = Header::ref_from_bytes(&bytes)?;
println!("{:#?}", hdr);
Ok(())
}The reported error is this: // error[E0597]: `bytes` does not live long enough
fn print_header(bytes: Vec<u8>) -> Result<()> {
// ----- binding `bytes` declared here
let hdr = Header::ref_from_bytes(&bytes)?;
// -----------------------^^^^^^-
// | |
// | borrowed value does not live long enough
// argument requires that `bytes` is borrowed for `'static`
println!("{:#?}", hdr);
Ok(())
}
//- `bytes` dropped here while still borrowedI found that rather puzzling, but I am far from experienced with rust, so that's not unusual. If you were to change the function definition to expect a // error[E0521]: borrowed data escapes outside of function
fn print_header(bytes: &[u8]) -> Result<()> {
// ----- - let's call the lifetime of this reference `'1`
// |
// `bytes` is a reference that is only valid in the function body
let hdr = Header::ref_from_bytes(&bytes)?;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// |
// `bytes` escapes the function body here
// argument requires that `'1` must outlive `'static`
println!("{:#?}", hdr);This error is more useful. How does Of course, it is the I believe this is very similar to (if not the same as) the issue described here: #2262 So the problem can be resolved by switching the line: let hdr = Header::ref_from_bytes(&bytes)?;to either let hdr = Header::ref_from_bytes(&bytes).unwrap();or let hdr = Header::ref_from_bytes(&bytes)
.map_err(|_| format_err!("ref_from_bytes failed"))?;And in that linked discussion, in addition to other changes, the user also switches I'm not really sure what my question is. I have no problem just mapping the error to something else, but thought I'd raise the issue just in case there was a better solution. |
Beta Was this translation helpful? Give feedback.
-
|
It's The correct solution is, yes, to map zerocopy's error to something else that meets these requirements. We're lightly looking into providing an API that would make this easier, but it's not on our near-term roadmap right now. |
Beta Was this translation helpful? Give feedback.
It's
anyhowthat imposes the'staticrequirement, since — under the hood — anyhowBoxes up (and type erases) the error value. The requirement specifically comes from this conversion, which is implicitly invoked by?.The correct solution is, yes, to map zerocopy's error to something else that meets these requirements. We're lightly looking into providing an API that would make this easier, but it's not on our near-term roadmap right now.