viperproject/prusti-dev

Error for missing model lifetime specifier recommends invalid syntax, has unclear fix

csgordon opened this issue · 3 comments

Here's a minimized example:

use prusti_contracts::*;

struct Blah<T> {
    _x: std::marker::PhantomData<T>,
}
#[model]
struct Blah<#[generic] T> {
    r: &T,
}

This complains because the r field in the model doesn't have a lifetime for the &T. But the error message I get is:

error[E0106]: missing lifetime specifier
 --> src/lib.rs:8:8
  |
8 |     r: &T,
  |        ^ expected named lifetime parameter
  |
help: consider introducing a named lifetime parameter
  |
6 ~ #[model]'a,
7 | struct Blah<#[generic] T> {
8 ~     r: &'a T,
  |

For more information about this error, try `rustc --explain E0106`.
error: could not compile `repro` (lib) due to previous error

But of course, the suggested fix is syntactically invalid, because you can't write a lifetime parameter there.

If I remove the T parameter and replace all of its occurrences with, say, u8, I get an error message that suggests adding a lifetime parameter to Blah and using it with that field. So it seems like there's an issue with the suggested fix just in the case where the affected struct already has generic parameters.

Things get a little weirder; compiling what I thought was the intended fix

use prusti_contracts::*;

struct Blah<T> {
    _x: std::marker::PhantomData<T>,
}
#[model]
struct Blah<'a, #[generic] T> {
    r: &'a T,
}

results in:

error[E0261]: use of undeclared lifetime name `'a`
 --> src/lib.rs:8:9
  |
6 | #[model]
  | -------- lifetime `'a` is missing in item created through this procedural macro
7 | struct Blah<'a, #[generic] T> {
8 |     r: &'a T,
  |         ^^ undeclared lifetime

For more information about this error, try `rustc --explain E0261`.
error: could not compile `repro` (lib) due to previous error

This second error persists even if I additionally add the 'a parameter to the original model as well, and even if I mark it #[generic].

Hi @csgordon! Thank you for reporting this. The high-level reason of the weird lifetime error is that specifications are implemented as a macro that desugars attributes into Rust code (we have a debugging flag to show that when running prusti-rustc from the command line). When lifetimes are involved, in some cases the desugarding would have to introduce lifetimes names to generate valid Rust code, but we didn't implement that. @Aurel300 might correct me, but I believe that type models with #[generic] are still very experimental.