How to resolve "indicate anonymous lifetime <'_>" error? - rust

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.

Related

Why does auto borrowing not occur in Rust if I implement `TryFrom` for a reference type?

Let's say I want to implement a conversion on a reference. In this case, it's a conversion from &f64 -> Foo.
use std::convert::{TryFrom, TryInto};
struct Foo {
a: f64
}
impl TryFrom<&f64> for Foo {
type Error = String;
fn try_from(value: &f64) -> Result<Foo, String> {
Ok(Foo {
a: *value
})
}
}
fn main(){
let foo: Foo = 5.0.try_into().unwrap();
let bar: Foo = (&5.0).try_into().unwrap();
}
(Yes of course this is a pointless and stupid example, but it helps simplify the problem)
Now, the second line in the main method, with manual borrowing, succeeds.
However, the first line in the main method, without the manual borrowing, fails with this error:
error[E0277]: the trait bound `Foo: From<{float}>` is not satisfied
--> src/main.rs:18:24
|
18 | let foo: Foo = 5.0.try_into().unwrap();
| ^^^^^^^^ the trait `From<{float}>` is not implemented for `Foo`
|
= note: required because of the requirements on the impl of `Into<Foo>` for `{float}`
note: required because of the requirements on the impl of `TryFrom<{float}>` for `Foo`
--> src/main.rs:7:6
|
7 | impl TryFrom<&f64> for Foo {
| ^^^^^^^^^^^^^ ^^^
= note: required because of the requirements on the impl of `TryInto<Foo>` for `{float}`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
Playground
Why is automatic borrowing not working here?
Just as the error message suggests, the problem is the trait bound Foo: From<{float}> is not satisfied. When matching traits, Rust will not perform any coercion but probing the suitable method. This is actually documented in The Rustonomicon, reads
Note that we do not perform coercions when matching traits (except for receivers, see the next page). If there is an impl for some type U and T coerces to U, that does not constitute an implementation for T.
and the next page says
Suppose we have a function foo that has a receiver (a self, &self or &mut self parameter). If we call value.foo(), the compiler needs to determine what type Self is before it can call the correct implementation of the function. ... If it can't call this function (for example, if the function has the wrong type or a trait isn't implemented for Self), then the compiler tries to add in an automatic reference. This means that the compiler tries <&T>::foo(value) and <&mut T>::foo(value). This is called an "autoref" method call.
So when matching the trait bound, Rust compiler will try to auto ref/deref on the type only. In addition, the dot operator in rust is just a syntax sugar of fully qualified function call. Thus 5.0.try_into().unwrap(); will become f64::try_into(5.0).unwrap(); and since TryInto is not implemented for f64, Rust will try to auto reference it by calling &f64::try_into(5.0).unwrap();. Now the compiler can find a version of TryInto implemented for &f64, however the type of argument still doesn't match: try_into for &f64 requires &f64 as parameter type, while the current call provides f64, and Rust compiler cannot do any coercion on parameters when checking trait bound. Thus the trait bound still doesn't match (&f64 cannot take f64 argument) and the check failed. Thus you will see the error message.

Passing local lifetime to satisfy trait

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.

How to read a lifetime error without looking at the code?

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.

Why doesn't `Box::into_raw` take `self` as parameter?

This simple program:
fn main() {
let b: Box<i32> = Box::new(1);
b.into_raw();
}
Produces this inconvenient error when compiled with Rust 1.12.0:
error: no method named `into_raw` found for type `Box<i32>` in the current scope
--> <anon>:3:7
|
3 | b.into_raw();
| ^^^^^^^^
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
= note: candidate #1 is defined in an impl for the type `Box<_>`
This is because into_raw is not defined to take self as parameter, but instead is defined as:
impl Box<T: ?Sized> {
fn into_raw(b: Box<T>) -> *mut T;
}
This seems inconvenient, and I cannot find a rationale.
So... why?
Because 99.995% of the time (statistic totally made up), you expect method calls to happen to the thing being pointed to, not to the pointer itself. As a result, the "smart pointer" types in Rust generally avoid doing anything to break that expectation. An obvious exception would be something like Rc/Arc implementing Clone directly.
Box implements Deref, which means that all methods that are enclosed by the Box are automatically made available; from the outside, Box<T> and T look and act the same.
If into_raw were a method instead of an associated function, it would shadow any into_raw method on the contained type.
There are other examples of these enhancing associated functions on Rc, such as downgrade or try_unwrap, or on Arc, such as make_mut.

Why does this struct member need two lifetimes?

I have the following struct:
struct PeekableRead<'a, R: Read> {
reader: &'a mut R,
peeked_octet: Option<u8>,
}
Which rustc does not like:
…:27:1: 30:2 error: the parameter type `R` may not live long enough [E0309]
…:27 struct PeekableRead<'a, R: Read> {
…:28 reader: &'a mut R,
…:29 peeked_octet: Option<u8>,
…:30 }
…:27:1: 30:2 help: run `rustc --explain E0309` to see a detailed explanation
…:27:1: 30:2 help: consider adding an explicit lifetime bound `R: 'a`...
…:27:1: 30:2 note: ...so that the reference type `&'a mut R` does not outlive the data it points at
…:27 struct PeekableRead<'a, R: Read> {
…:28 reader: &'a mut R,
…:29 peeked_octet: Option<u8>,
…:30 }
If I add the lifetime to R, as in, R: Read + 'a, it works. But why? Doesn't the 'a on the reference specify the lifetime? Must not reader: &'a mut R, in a struct PeekableRead<'a> live as long as the struct itself, and thus, "long enough"?
Oddly, I seem to need both; if I add 'a to R and remove it from the reference, I still get error: missing lifetime specifier. The only way I get a successful compilation is with both, but to me, they appear to specify the same thing redundantly.
(Also, why does rustc output the struct twice in the output? The second one looks like a suggestion of what to do, but appears to be exactly the same as what I have…)
Doesn't the 'a on the reference specify the lifetime?
It specifies the lifetime of the reference, but not the lifetime of the value being pointed to. Which explains your observation that
if I add 'a to R and remove it from the reference, I still get error: missing lifetime specifier.
For the struct to be valid we need both: the value being pointed to must still be alive, and so must the reference. (Although logically, the first condition is implied by the second, since a reference can never outlive the value it points to.).
The lifetime parameter on a reference designates the lifetime of the referent (i.e. the object the reference points to). That object may be a reference, or a complex object that contains one or more references. However, when you use a trait, the lifetime of the objects behind those references are somewhat hidden (the trait itself doesn't know about those lifetimes); lifetime bounds are what lets the compiler reason correctly about those lifetimes.
When you use a generic type behind a reference, you need to add a bound to ensure that instances of that type don't contain references that are shorter than the reference to that those instances. Bounds are not implicitly added just based on how you use types: the bounds should not change based on the details of what fields are in the struct and what type you define them to be.
For example, the type &'f File (for each 'f) implements Read. We can instantiate PeekableRead with that type: this gives us a PeekableRead<&'f File>. PeekableRead<&'f File> stores a mutable reference to a &'f File, so the concrete type of the reader field is &'a mut &'f File. In order for such a reference to be valid, 'a must be shorter or equal to 'f. If 'f was shorter than 'a, then you could replace the &'f File with one that would be dropped before the reference is dropped, leading to a dangling pointer. When you add the 'a bound to R (i.e. when you write R: Read + 'a), you say "instances of R must outlive 'a" (i.e. R may not contain references shorter than 'a).

Resources