Skip to content
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

Confusing rustc error message on generic struct with misleading suggestion #199

Open
molenzwiebel opened this issue May 2, 2023 · 1 comment

Comments

@molenzwiebel
Copy link

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):

image

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,
    |

@csnover
Copy link
Collaborator

csnover commented Jul 7, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants