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.
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:
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.
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.
Related
Question
I usually use c++ lang, and recently I'm learning rust lang but now confusing the concept of lifetime.
My understanding for lifetime is as follows. Is this correct?
Lifetime is an attribute of instance.
Lifetime represents the valid scope of instance.
Background of above question
The following code is a sample code at here.
{
let r; // ---------+-- 'a
// |
{ // |
let x = 5; // -+-- 'b |
r = &x; // | |
} // -+ |
// |
println!("r: {}", r); // |
} // ---------+
The document said that 'a is a lifetime, and 'b is also a lifetime.
but if my understanding is correct, 'a is not lifetime, just scope of symbol r... Is `a really lifetime?
P.S.
There are two things named "a lifetime": value's lifetime, and the lifetime attached to a reference.
Thank you! Maybe I understood a little bit more than before...
A lifetime is not so much an attribute of an instance, it's more the opposite way around; when an instance is borrowed (a reference is taken), it is borrowed for a specific lifetime. The borrow checker will try to minimise the lifetime of the borrow so that it can be as permissive as possible whilst ensuring code is still safe.
Lifetimes are your way of communicating how long you need a reference to last to the compiler, and given that information, the compiler will check that nothing violates that rule (by holding the reference for longer), and that the reference is available for at least as long as you require it. This can be thought of in much the same way that a compiler can check type to ensure you don't assign a float to an integer.
Lifetimes are also independent of scope. Rust now has non-lexical lifetimes (https://github.com/rust-lang/rfcs/pull/2094 — see What are non-lexical lifetimes? for more detailed explanation), meaning that within a given scope, the borrow checker is capable of determining that borrows have shorter lifetimes than the containing scope.
tl;dr blocked by "argument requires that `x` is borrowed for `'y`"; how can I coerce variable x to lifetime 'y?
Given the following code, I'm blocked when trying to create the Box pointer pointing to a reference. I know the referenced object instance lives long enough. However, the rust compiler is concerned it does not.
How do I tell the rust compiler that Box::new(&thing) is valid for the lifetime of the containing struct instance?
Code example
This code is essentially:
Things (a Vec), holding multiple Things
counter of Things (a HashMap), holding multiple Box pointers to different &Thing as keys, a u64 count as values
(My best attempt at) a minimal example (rust playground):
use std::collections::HashMap;
type Thing<'a> = (&'a str, usize);
type Things<'a> = Vec<Thing<'a>>;
type ThingsCounterKey<'a> = Box<&'a Thing<'a>>;
type ThingsCounter<'a> = HashMap<ThingsCounterKey<'a>, u64>;
pub struct Struct1<'struct1> {
things1: Things<'struct1>,
thingscounter1: ThingsCounter<'struct1>,
}
impl<'struct1> Struct1<'struct1> {
pub fn new() -> Struct1<'struct1> {
Struct1{
things1: Things::new(),
thingscounter1: ThingsCounter::new(),
}
}
fn things_update(&mut self, thing_: Thing<'struct1>) {
self.things1.push(thing_);
let counter = self.thingscounter1.entry(
ThingsCounterKey::new(&thing_)
).or_insert(0);
*counter += 1;
}
}
fn main() {
let mut s1 = Struct1::new();
for (x, y) in [("a", 1 as usize), ("b", 2 as usize)] {
s1.things_update((x, y));
}
}
This results in compiler error:
error[E0597]: `thing_` does not live long enough
--> src/main.rs:24:35
|
14 | impl<'struct1> Struct1<'struct1> {
| -------- lifetime `'struct1` defined here
...
24 | ThingsCounterKey::new(&thing_)
| ----------------------^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `thing_` is borrowed for `'struct1`
...
27 | }
| - `thing_` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error
How can I tell the rust compiler "&thing_ has the lifetime of 'struct1"?
Similar questions
Before this Question is marked as duplicate, these questions are similar but not quite the same. These Questions address 'static lifetimes or other slightly different scenarios.
Argument requires that value is borrowed for 'static not working for non copy value
Argument requires that _ is borrowed for 'static - how do I work round this?
"argument requires that record is borrowed for 'static" when using belonging_to associations with tokio-diesel
(tokio::spawn) borrowed value does not live long enough -- argument requires that sleepy is borrowed for 'static
Rust lifetime syntax when borrowing variables
Borrow data out of a mutex "borrowed value does not live long enough"
Rust: argument requires that borrow lasts for 'static
thing_ is passed by value. Its lifetime ends at the end of things_update. That means, the reference to thing_ becomes invalid after the end of the function but still be held by the struct, which is certainly should be rejected.
Like many times, actually the compiler is right and you were wrong. The compiler prevented you from use-after-free.
thing_ doesn't live long enough: you pushed a copy of it into the vector. It was clear if you'd used a type that isn't Copy:
type Thing<'a> = (&'a str, String);
// ...
Besides the previous error, now you also get:
error[E0382]: borrow of moved value: `thing_`
--> src/main.rs:24:35
|
21 | fn things_update(&mut self, thing_: Thing<'struct1>) {
| ------ move occurs because `thing_` has type `(&str, String)`, which does not implement the `Copy` trait
22 | self.things1.push(thing_);
| ------ value moved here
23 | let counter = self.thingscounter1.entry(
24 | ThingsCounterKey::new(&thing_)
| ^^^^^^^ value borrowed here after move
Playground.
In other case, you would have to first push the item into the vector and then retrieve a reference to the pushed item there, like:
self.things1.push(thing_);
let counter = self.thingscounter1.entry(
ThingsCounterKey::new(self.things1.last().unwrap())
).or_insert(0);
But in this case it will not work, and you'll get a long "cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements" error. This is because you're essentially trying to do the impossible: create a self-referential struct. See Why can't I store a value and a reference to that value in the same struct? for more about this problem and how to solve it.
warning: hidden lifetime parameters in types are deprecated
--> asd/src/app/qwe.rs:88:45
|
88 | fn add_meta_from_args(&mut self, args: &ArgMatches) -> AppRun {
| ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
Where should I specify this anonymous lifetime? I don't really understand the need for it either. If the parameter is borrowed, why does it need a lifetime as well?
The ArgMatches<'a> struct within clap is generic over lifetimes. You haven't written out the full type of args in your function because you have omitted the lifetime parameter of the ArgMatches struct, which is why the compiler is complaining the type parameter is "hidden" and is suggesting you provide the full type for args by writing ArgMatches<'_> to make your code more explicit and clear.
I have a generic function creating a local object and taking a trait specifying what to do with that object. The trait takes the reference to the object and holds it for it's lifetime (to avoid passing it again and again to every function call). It dies before the
fn do_stuff<'a, T>()
where T : BigBorrower<'a>
{
let borrowee = Borrowed{ data : 1 };
{
let _borrowee = T::new(&borrowee);
}
}
This is the function call. Because the lifetime for trait has to be specified in function declaraion, it makes the compiler think the lifetime extends lifetime of _borrowee.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a445fb4ab7befefbadd3bdb8fb43c86a
|
24 | fn do_stuff<'a, T>()
| -- lifetime `'a` defined here
...
29 | let _borrowee = T::new(&borrowee);
| -------^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `borrowee` is borrowed for `'a`
30 | }
31 | }
| - `borrowee` dropped here while still borrowed
You've just hit one of the issues with lifetimes and the compiler. Once you realize why it happens, it makes sense.
Your method call enforces a lifetime 'a for the generic type you're providing. This means, amongst other things, that this lifetime needs to be respected and that all objects are required to live for that long. In practice, when you are doing that, the lifetime is that of the function call.
By passing T::new() a reference to a local variable, you are forcing the compiler to pick a lifetime that is inferior to 'a (since it will not outlive the function call), and thus, you are going against your own requirements.
Typically, the way you solve this is to split your do_stuff<'a, T> into two, like on this playground sample. This makes the lifetime check palatable by the compiler, seeing as the life expectancy of that reference is guaranteed to be longer than that of the function being called.
Do note that I renamed your method new in the trait and implementations to borrow, as that's closer to what it is.
Why does this, with no type annotation on the closure, compile?
fn transform(input: &Vec<Vec<String>>) {
input.iter().flat_map(|words| words.iter());
}
But this doesn't?
fn transform(input: &Vec<Vec<String>>) {
input.iter().flat_map(|words: &Vec<String>| words.iter());
}
Is the inferred type not &Vec<String>? Or do I need to annotate the lifetime too, as this seems to be about the closure not living long enough?
The error for in the latter snippet is
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:2:55
|
2 | input.iter().flat_map(|words: &Vec<String>| words.iter());
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 2:48...
--> src/main.rs:2:49
|
2 | input.iter().flat_map(|words: &Vec<String>| words.iter());
| ^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:2:49
|
2 | input.iter().flat_map(|words: &Vec<String>| words.iter());
| ^^^^^
note: but, the lifetime must be valid for the method call at 2:4...
--> src/main.rs:2:5
|
2 | input.iter().flat_map(|words: &Vec<String>| words.iter());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so type `fn(std::slice::Iter<'_, std::vec::Vec<std::string::String>>, [closure#src/main.rs:2:27: 2:61]) -> std::iter::FlatMap<std::slice::Iter<'_, std::vec::Vec<std::string::String>>, std::slice::Iter<'_, std::string::String>, [closure#src/main.rs:2:27: 2:61]> {<std::slice::Iter<'_, std::vec::Vec<std::string::String>> as std::iter::Iterator>::flat_map::<std::slice::Iter<'_, std::string::String>, [closure#src/main.rs:2:27: 2:61]>}` of expression is valid during the expression
--> src/main.rs:2:5
|
2 | input.iter().flat_map(|words: &Vec<String>| words.iter());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The compiler is worried that your code can produce dangling pointers. When you leave off the type annotation, the compiler correctly infers the lifetime of the inner references in relation to the outer references.
However, when you annotate the type and don't explain to the compiler how the lifetimes of the internal references relate to the outer references (that is, how the words: &Vec<String>/internal references relate to the input: &Vec<Vec<String>>/outer references), the compiler freaks out.
The easy fix, is to let the compiler know that the inner references live at least the same lifetime as the outer one:
fn transform<'a>(input: &'a Vec<Vec<String>>) {
input.iter().flat_map(|words: &'a Vec<String>| words.iter());
}
Hopefully that makes sense. In Rust, a reference can't outlive what it references. In the eyes of the compiler, your input reference might go away before your words references do (which is bad because words references items inside input). So if you're not going to let the compiler infer the lifetimes, you need to be explicit about it.