Closed
Description
Failing Code
Consider the following code:
use std::io::{self, prelude::*};
use std::sync::Arc;
struct IoArc<T>(Arc<T>);
impl<T> Read for IoArc<T>
where
&T: Read,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(&mut &*self.0).read(buf)
}
}
This fails with a pretty gnarly error about how &IoArc<T>
doesn't have a
lifetime, parameter T doesn't live long enough, and we should consider adding
a lifetime. It (wrongly) suggest we may want to add a static lifetime. Which
is not the right solution.
Compiling playground v0.0.1 (/playground)
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> src/lib.rs:8:5
|
8 | &T: Read,
| ^ explicit lifetime name needed here
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:6:1
|
6 | impl<T> Read for IoArc<T>
| ^ - help: consider adding an explicit lifetime bound `T: 'static`...
| _|
| |
7 | | where
8 | | &T: Read,
9 | | {
... |
12 | | }
13 | | }
| |_^
|
note: ...so that the reference type `&'static T` does not outlive the data it points at
--> src/lib.rs:6:1
|
6 | / impl<T> Read for IoArc<T>
7 | | where
8 | | &T: Read,
9 | | {
... |
12 | | }
13 | | }
| |_^
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:10:5
|
6 | impl<T> Read for IoArc<T>
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
10 | / fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
11 | | (&mut &*self.0).read(buf)
12 | | }
| |_____^
|
note: ...so that the reference type `&'static T` does not outlive the data it points at
--> src/lib.rs:10:5
|
10 | / fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
11 | | (&mut &*self.0).read(buf)
12 | | }
| |_____^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0310`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
Working Code
Instead the resolution is to add a higher-rank trait bound, like this:
use std::io::{self, prelude::*};
use std::sync::Arc;
struct IoArc<T>(Arc<T>);
impl<T> Read for IoArc<T>
where
for<'a> &'a T: Read, // <-- we added for<'a> to get a lifetime
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(&mut &*self.0).read(buf)
}
}
Diagnostics Suggestions
I understand that this is not a particularly common pattern, but the compiler
really isn't of much help when trying to figure this out. A better suggestion
here would have been:
Compiling playground v0.0.1 (/playground)
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> src/lib.rs:8:5
|
8 | &T: Read,
| ^ explicit lifetime name needed here
help: Consider adding a higher-rank trait bound:
--> src/lib.rs:8:5
|
8 | for<'a> &'a T: Read,
|
With if 'static
is sometimes the right solution, perhaps two help texts would make sense:
help: ...or use a static lifetime:
--> src/lib.rs:8:5
|
8 | &'static T: Read,
|