I have a struct like this -
pub struct A {
pub f: &str,
}
When I later try to assign a &str value to the struct using this -
fn use(&self, t: &str){
let a = A {
f: self.t,
};
}
I get an error saying -
pub f: &str,
| ^ expected named lifetime parameter
I then changed my struct to use named lifetime parameters -
pub struct A<'i> {
pub f: &'i str,
}
But it now gives error -
implicit elided lifetime not allowed here
note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
Can someone explain the second error and how can I fix it?
Use String instead of &str
pub struct A {
pub f: String,
}
// use .to_string() to convert &str to String
fn use(&self, t: &str){
let a = A {
f: t.to_string(),
};
}
Without seeing a more complete picture of your code it's hard to say what exactly is wrong, but you are probably missing a lifetime specifier on your impl. For example, this code will compile:
pub struct A<'a> {
pub f: &'a str,
}
impl<'a> A<'a> {
fn new(t: &'a str) -> Self {
A {
f: t,
}
}
}
fn main() {
A::new("hi");
}
You need to implement A for the generic lifetime 'a, otherwise the compiler will imply the 'static lifetime which conflicts with your struct definition.
This in most cases isn't very practical however, and you probably want your struct to hold a string using the String type instead which has ownership over the string rather than a reference.
Related
I currently have code that looks kind of like this:
struct People {
names: Vec<String>,
ages: Vec<i32>,
}
impl People {
fn iter_people<'a>(&'a self) -> PeopleIterator<'a> {
return PeopleIterator {
names_iterator: Box::new(self.names.iter()),
ages: Box::new(self.ages.iter()),
};
}
}
struct PeopleIterator<'a> {
names_iterator: Box<dyn Iterator<Item = &'a String>>,
ages: Box<dyn Iterator<Item = &'a i32>>,
}
impl<'a> Iterator for PeopleIterator<'a> {
...snip...
}
I am aware that I should model a person as a struct Person and then have a Vec<Person> to model people but this is just a simplification of my actual code.
Anyway, the Rust compiler tells me this:
lifetime may not live long enough
requirement occurs because of the type PeopleIterator<'_>, which makes the generic argument '_ invariant
I have looked at the suggested link for subtyping and variance but I need to read it a few more times to actually understand it.
What stumps me is that I would expect both my iterators self.names.iter() and self.ages.iter() to live as long as self and I have declared that self should live as long as PeopleIterator. However, when I look at the iter() function, it does not make this constraint but instead has an anonymous lifetime '_. I am guessing this is the problem but I am confused and don't know how to fix it :(
The problem is the lifetime of the iterator itself in Box<dyn Iterator<Item = &'a String>> is by default bound to be 'static, but that's not possible for an iterator containing non static references like anything from &'a self. The solution is to specify an explicit lifetime bound:
struct PeopleIterator<'a> {
names_iterator: Box<dyn Iterator<Item = &'a String> + 'a>,
ages: Box<dyn Iterator<Item = &'a i32> + 'a>,
}
Personally I'd just use generics instead of static dispatch avoiding some indirection and the whole problem from the beginning:
impl People {
fn iter_people(&self) -> PeopleIterator<impl Iterator<Item = &String>, impl Iterator<Item = &i32>> {
return PeopleIterator {
names_iterator: self.names.iter(),
ages: self.ages.iter(),
};
}
}
struct PeopleIterator<N, A> {
names_iterator: N,
ages: A,
}
I am having trouble figuring out what lifetime parameter will work for this, so my current workarounds include transmutes or raw pointers. I have a structure holding a function pointer with a generic as a parameter:
struct CB<Data> {
cb: fn(Data) -> usize
}
I would like to store an instance of that, parameterized by some type containing a reference, in some other structure that implements a trait with one method, and use that trait method to call the function pointer in CB.
struct Holder<'a> {
c: CB<Option<&'a usize>>
}
trait Exec {
fn exec(&self, v: &usize) -> usize;
}
impl<'a> Holder<'a> {
fn exec_aux(&self, v: &'a usize) -> usize {
(self.c.cb)(Some(v))
}
}
impl<'a> Exec for Holder<'a> {
fn exec(&self, v: &usize) -> usize
{
self.exec_aux(v)
}
}
This gives me a lifetime error for the 'Exec' impl of Holder:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
Simply calling exec_aux works fine as long as I don't define that Exec impl:
fn main() {
let h = Holder { c: CB{cb:cbf}};
let v = 12;
println!("{}", h.exec_aux(&v));
}
Also, making CB not generic also makes this work:
struct CB {
cb: fn(Option<&usize>) -> usize
}
The parameter in my actual code is not a usize but something big that I would rather not copy.
The lifetimes in your Exec trait are implicitly this:
trait Exec {
fn exec<'s, 'a>(&'s self, v: &'a usize) -> usize;
}
In other words, types that implement Exec need to accept any lifetimes 's and 'a. However, your Holder::exec_aux method expects a specific lifetime 'a that's tied to the lifetime parameter of the Holder type.
To make this work, you need to add 'a as a lifetime parameter to the Exec trait instead, so that you can implement the trait specifically for that lifetime:
trait Exec<'a> {
// ^^^^ vv
fn exec(&self, v: &'a usize) -> usize;
}
impl<'a> Exec<'a> for Holder<'a> {
// ^^^^ vv
fn exec(&self, v: &'a usize) -> usize
{
self.exec_aux(v)
}
}
The problem here is that the Exec trait is too generic to be used in this way by Holder. First, consider the definition:
trait Exec {
fn exec(&self, v: &usize) -> usize;
}
This definition will cause the compiler to automatically assign two anonymous lifetimes for &self and &v in exec. It's basically the same as
fn exec<'a, 'b>(&'a self, v: &'b usize) -> usize;
Note that there is no restriction on who needs to outlive whom, the references just need to be alive for the duration of the method call.
Now consider the definition
impl<'a> Holder<'a> {
fn exec_aux(&self, v: &'a usize) -> usize {
// ... doesn't matter
}
}
Since we know that &self is a &Holder<'a> (this is what the impl refers to), we need to have at least a &'a Holder<'a> here, because &'_ self can't have a lifetime shorter than 'a in Holder<'a>. So this is saying that the two parameters have the same lifetime: &'a self, &'a usize.
Where it all goes wrong is when you try to combine the two. The trait forces you into the following signature, which (again) has two distinct implicit lifetimes. But the actual Holder which you then try to call a method on forces you to have the same lifetimes for &self and &v.
fn exec(&self, v: &usize) -> usize {
// Holder<'a> needs `v` to be `'a` when calling exec_aux
// But the trait doesn't say so.
self.exec_aux(v)
}
One solution is to redefine the trait as
trait Exec<'a> {
fn exec(&'a self, v: &'a usize) -> usize;
}
and then implement it as
impl<'a> Exec<'a> for Holder<'a> {
fn exec(&'a self, v: &'a usize) -> usize {
self.exec_aux(v)
}
}
I have a struct with string (&str) field in it,
struct Test<>{
name: &str,
city: &str,
}
while compiling this struct it returned a lifetime error and according to compiler suggestion added lifetime to it <'a> which worked.
use std::fmt;
#[derive(Debug)]
struct Test<'a>{
name: &'a str,
city: &'a str,
}
impl fmt::Display for Test {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "name:{} city:{}", self.name,self.city)
}
}
fn main(){
let a = Test{name:"John",city:"London"};
println!("{}",a);
}
I then tried to implement a display trait on this struct but its giving this error.
| impl fmt::Display for Test {
| ^^^^- help: indicate the anonymous lifetime: `<'_>`
How to implement display trait for a struct with lifetime in rust?
Short answer: use
impl<'a> fmt::Display for Test<'a>
I'd like to write some code like the following:
struct Foo {
foo: usize
}
impl Foo {
pub fn get_foo<'a>(&'a self) -> &'self usize {
&self.foo
}
}
But this doesn't work, failing with invalid lifetime name: 'self is no longer a special lifetime.
How can I return a reference that lives as long as the object itself?
You don't want the reference to live exactly as long as the object. You just want a borrow on the object (quite possibly shorter than the entire lifetime of the object), and you want the resulting reference to have the lifetime of that borrow. That's written like this:
pub fn get_foo<'a>(&'a self) -> &'a usize {
&self.foo
}
Additionally, lifetime elision makes the signature prettier:
pub fn get_foo(&self) -> &usize {
&self.foo
}
In your example the lifetime of self is 'a so the lifetime of the returned reference should be 'a:
pub fn get_foo<'a>(&'a self) -> &'a usize {
&self.foo
}
However the compiler is able to deduce (lifetime elision) the correct lifetime in simple cases like that, so you can avoid to specify lifetime at all, this way:
pub fn get_foo(&self) -> &usize {
&self.foo
}
Look here for lifetime elision rules
I understand how lifetime parameters apply to functions and structs, but what does it mean for a trait to have a lifetime parameter? Is it a shortcut to introduce a lifetime parameter to its methods, or is it something else?
If you have a trait with a lifetime bound, then implementors of the trait can participate in the same lifetime. Concretely, this allows you to store references with that lifetime. It is not a shortcut for specifying lifetimes on member methods, and difficulty and confusing error messages lie that way!
trait Keeper<'a> {
fn save(&mut self, v: &'a u8);
fn restore(&self) -> &'a u8;
}
struct SimpleKeeper<'a> {
val: &'a u8,
}
impl<'a> Keeper<'a> for SimpleKeeper<'a> {
fn save(&mut self, v: &'a u8) {
self.val = v
}
fn restore(&self) -> &'a u8 {
self.val
}
}
Note how both the struct and the trait are parameterized on a lifetime, and that lifetime is the same.
What would the non-trait versions of save() and restore() look like for SimpleKeeper<'a>?
Very similar, actually. The important part is that the struct stores the reference itself, so it needs to have a lifetime parameter for the values inside.
struct SimpleKeeper<'a> {
val: &'a u8,
}
impl<'a> SimpleKeeper<'a> {
fn save(&mut self, v: &'a u8) {
self.val = v
}
fn restore(&self) -> &'a u8 {
self.val
}
}
And would they mean exactly the same thing as the the trait version?
Yep!