0
votes

I'm getting the following lifetime error:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> prusti-viper/src/procedures_table.rs:42:40
   |
42 |         let mut cfg = self.cfg_factory.new_cfg_method(
   |                                        ^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 40:5...
  --> prusti-viper/src/procedures_table.rs:40:5
   |
40 | /     pub fn set_used(&mut self, proc_def_id: ProcedureDefId) {
41 | |         let procedure = self.env.get_procedure(proc_def_id);
42 | |         let mut cfg = self.cfg_factory.new_cfg_method(
43 | |             // method name
...  |
135| |         self.procedures.insert(proc_def_id, method);
136| |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> prusti-viper/src/procedures_table.rs:42:23
   |
42 |         let mut cfg = self.cfg_factory.new_cfg_method(
   |                       ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'v as defined on the impl at 22:1...
  --> prusti-viper/src/procedures_table.rs:22:1
   |
22 | impl<'v, P: Procedure> ProceduresTable<'v, P> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...so that the expression is assignable:
           expected viper::Method<'v>
              found viper::Method<'_>

error: aborting due to previous error

Without looking at the code, just by reading the error message, is it possible to understand to which lifetimes/references/borrows is the error message referring to? Here is the message annotated with my questions:

error[E0495]: cannot infer an appropriate lifetime for autoref (what is autoref?) due to conflicting requirements

note: first, the lifetime (which lifetime?) cannot outlive the anonymous lifetime #1 (the one of &mut self, ok) defined on the method body at 40:5...

...so that reference (which reference?) does not outlive borrowed content (which borrowed content?)

but, the lifetime must be valid for the lifetime 'v as defined on the impl at 22:1... (why these constraints?)

For example, I'm looking for an explanation like "In error message E0495 the lifetime that cannot outlive the anonymous lifetime #1 is always the lifetime of self, in other words #1 again".

By looking at existing answers to similar questions (https://stackoverflow.com/a/35519236/2491528, https://stackoverflow.com/a/30869059/2491528, https://stackoverflow.com/a/41271422/2491528), I can't find an explanation of what the error message is referring to. Sometimes the answer just writes "in this case the lifetime is 'a", but I'm wondering how to understand that it's 'a and not some other 'b. Other times the answer involves reasoning on the source code, but that would be one of the following steps for me: first of all read the message and understand what it's referring to, then understand the error (in this case, probably conflicting lifetime requirements), then look at the code and try to fix the error.

1
I'd strongly encourage you to produce a minimal reproducible example that produces these errors. There are some tips for producing a Rust MCVE on the tag wiki page. We aren't mystical gurus that magically divine error messages; we need code to look at the same as anyone else. While you are at it, please edit your question to explain why existing questions that talk about these error messages aren't good enough.Shepmaster
I think I clarified a bit the question. The focus is more on the error message than on the code itself (that I would like to fix, sure, but later).Federico
There is no MCVE, but on purpose: my question is how to parse the error message, that seems very specific ("the lifetime", "that reference"...) but I personally can't tell what it is referring to. Is the error message so useless without the code?Federico

1 Answers

7
votes

cannot infer an appropriate lifetime for autoref due to conflicting requirements

This is the key part of the error. There are two (or more) requirements on a lifetime, and they conflict. The "autoref" means the reference that's taken by calling a method that takes &self. The quoted line of code indicates which method call is erroneous.

note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 40:5

This is the first conflicting requirement. "The lifetime" means the one referred to in the first message: the one it's trying to infer, for this autoref. It can't outlive the object you're calling the method on. The quoted code indicates the lifetime of that object. In this case, the lifetime is the whole method that the erroneous line is in, because the object you're borrowing is a member of that method's &mut self.

note: ...so that reference does not outlive borrowed content

This just explains that a bit further. "That reference" - the autoref you're trying to take - can't outlive the object that &mut self refers to.

note: but, the lifetime must be valid for the lifetime 'v as defined on the impl at 22:1...

The "but" here introduces the second requirement, which conflicts with the first requirement.

You ask "why these constraints?", and the compiler explains right away:

note: ...so that the expression is assignable:
expected viper::Method<'v>
found viper::Method<'_>

The assignment in question is the one in the erroneous line. You're assigning the result of new_cfg_method to cfg. The "expected" is the left hand-side of the assignment, cfg, which must be of type viper::Method<'v>. The "found" is the right-hand side, the result of the method call, which has type viper::Method<'_>. '_ means the lifetime the compiler is trying to infer. That is, it's the way you subsequently use cfg that means it must have the lifetime 'v. Why that is depends on the code that's not quoted in the error message.

To fix this, you need to do one of the following:

  1. Cut out the first requirement. Change new_cfg_method so that the lifetime of its result is not tied to the lifetime of the object you call it on: perhaps by removing some references it contains.
  2. Cut out the second requirement. Change the code that uses cfg so it doesn't need to have the lifetime 'v. Again, this might be achieved by removing some references in viper::Method.

If you can't do either, you might need to introduce Cell or something else to manage lifetimes dynamically instead of statically.