binrw
binrw copied to clipboard
Confusing rustc error message on generic struct with misleading suggestion
I have the following:
#[derive(Debug, BinRead)]
pub struct Array<T>
where
T: for<'a> BinRead<Args<'a> = ()>,
{
_count: u32,
#[br(count = _count)]
pub data: Vec<T>,
}
For this, rustc complains about a missing lifetime bound on T
, but does so in an interesting manner (see expando at the end for the full message):
The correct solution here is to either add a 'static
bound to T
(if we're fine with disallowing a borrowed T), or to add a lifetime bound to the struct (and a PhantomData). Perhaps that could be made clearer.
Full message
error[E0310]: the parameter type `T` may not live long enough
--> src\base_binrw.rs:159:17
|
159 | #[derive(Debug, BinRead)]
| ^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
= note: this error originates in the derive macro `BinRead` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider adding an explicit lifetime bound...
|
162 | T: for<'a> BinRead<Args<'a> = ()> + 'static,
| +++++++++
error[E0311]: the parameter type `T` may not live long enough
--> src\base_binrw.rs:159:17
|
159 | #[derive(Debug, BinRead)]
| ^^^^^^^
|
note: the parameter type `T` must be valid for the anonymous lifetime defined here...
--> src\base_binrw.rs:159:17
|
159 | #[derive(Debug, BinRead)]
| ^^^^^^^
note: ...so that the type `T` will meet its required lifetime bounds
--> src\base_binrw.rs:159:17
|
159 | #[derive(Debug, BinRead)]
| ^^^^^^^
= note: this error originates in the derive macro `BinRead` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider adding an explicit lifetime bound...
|
159 ~ #[derive(Debug, 'a, BinRead)]
160 | pub struct Array<T>
161 | where
162 ~ T: for<'a> BinRead<Args<'a> = ()> + 'a,
|
I can modify the diagnostic to not give an obviously wrong suggestion about where to place a lifetime, but E0311 is giving a bogus suggestion in this situation because impl<T> BinRead for Vec<T>
is constrained to T: 'static
(due to fake specialisation). As a result, the only correct actions are either to add T: 'static
or to use a different parse_with
function that does not constrain T
. It seems to me that rustc should not be emitting these suggestions at all since they will never work—applying the suggestion just causes it to emit the same suggestion again with a different lifetime name.
I can’t think of a way to reliably communicate this information in a useful way. proc-macros don’t have the ability to retrieve type information so it’s not possible to know for sure what Vec
is to see how it is being used and emit a custom error, nor am I aware of a way to suppress the bad E0311 diagnostic.