Need help on lifetime issue - rust

pub struct Decoder<'a> {
reader: &'a mut io::Reader+'a,
}
impl<'a> Decoder<'a> {
pub fn from_reader(r: &'a mut io::Reader) -> Decoder<'a> {
Decoder {
reader: r,
}
}
}
// shortcut method to accept bytes to decode
pub fn decode<'a, T: Decodable<Decoder<'a>, IoError>>(data: Vec<u8>) -> DecodeResult<T> {
let mut r = MemReader::new(data);
let mut decoder = Decoder::from_reader(&mut r); // error: `r` does not live long enough
Decodable::decode(&mut decoder)
}
I have two question here.
How do you read this declaration(what it means) reader: &'a mut io::Reader+'a. Which I was referencing the code from the std json encoder.
I write a shortcut method to wrap Vec<u8> with MemReader, so that I can just interfacing io::Reader. But the compiler complains error:rdoes not live long. How to make it right.
Update: I upload the code to github.

The first 'a means that the Reader object itself has lifetime 'a. The second 'a means that the Reader object doesn't contain references that outlive 'a. Since Reader is a trait, it could be implemented by a struct that has lifetime parameters. This bound applies to those potential lifetime parameters.
The problem is with the bound on T: Decodable<Decoder<'a>, IoError> references the lifetime parameter 'a. However, the Decoder you're creating references a local variable, whereas 'a refers to a lifetime that lives longer than the function call (because it's an input parameter specified implicitly at the call site).
I think there's no way to make this function compile successfully without unsafe code for the moment. In fact, Encoder::buffer_encode seems to be having the same issue (#14302) and uses a similar workaround. transmute allows us to coerce the local lifetime to 'a.
pub fn decode<'a, T: Decodable<Decoder<'a>, IoError>>(data: Vec<u8>) -> DecodeResult<T> {
let mut r = MemReader::new(data);
let mut decoder = unsafe { mem::transmute(Decoder::from_reader(&mut r)) };
Decodable::decode(&mut decoder)
}

Related

How can I make `Box<dyn Iterator>` peekable and avoid lifetime errors?

I have the following type definition:
pub struct UTF8Chars {
bytes: Peekable<Box<dyn Iterator<Item = u8>>>,
}
Now I'm wondering how to actually create an instance of this struct.
I've tried (and yes, this is inside a trait implementation if that is an important detail):
impl<'a> ToUTF8Chars for &'a str {
fn utf8_chars(self) -> UTF8Chars {
let bytes = Box::new(self.bytes()).peekable();
UTF8Chars { bytes }
}
}
That gives me the error:
expected struct `Peekable<Box<(dyn Iterator<Item = u8> + 'static)>>`
found struct `Peekable<Box<std::str::Bytes<'_>>>`
Playground
Forgive me if I try weird things, but I haven't gotten the hang of this intricate trait stuff yet. For all I know, rust-analyzer was telling me that Bytes in fact an impl Iterator<Item = u8>. So, next thing I tried was casting it first:
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
UTF8Chars { bytes: bytes.peekable() }
That sort of works, but now the borrow checker is complaining:
impl<'a> ToUTF8Chars for &'a str {
-- lifetime `'a` defined here
fn utf8_chars(self) -> UTF8Chars {
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
I'm not exactly sure what is going out of scope here... as far as I know, I own the result from .bytes() (I also tried with an additional .clone() in case that assumption was incorrect), I own the Box, the Box is passed to Peekable, and finally Peekable is passed to UTF8Chars. What exactly is the issue here? Why do I somehow need to outlive static...?
I found this issue that seems similar, sadly no answer: Peekable of an Iterator in struct.
Why I want to do this?
Well, mainly because I don't really care, or am unable to care what exactly the underlying data is. I just need to know that I can .peek(), and .next(), etc. This is, because sometimes I want to assign different things to self.bytes. For example, Chain<...>, or Copied<...> instead of a simple vec::IntoIter<...>.
If there is an alternative approach to this, I'm happy to hear about it.
So, next thing I tried was casting it first:
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
This is the right thing to do in this situation, though I would write it with a type annotation on the let, instead of as.
let bytes: Box<dyn Iterator<Item = u8>> = Box::new(self.bytes());
In particular, there must be a point at which the unsizing coercion from Box<Bytes> to Box<dyn Iterator<Item = u8>> happens, and that point must be before the Box is contained in something else (because it actually produces a different Box, one with a vtable pointer added).
In some cases, just as _ (unspecified type) is sufficient to prompt the compiler into not immediately concluding that the type is the same as the incoming type.
I'm not exactly sure what is going out of scope here...
Every trait object (dyn) type has a lifetime, often implicit. This lifetime specifies how long instances of that type are guaranteed valid — or, from the opposite perspective, what references the trait object is allowed to borrow/contain.
When you don't specify that lifetime, and the trait object is in a Box, lifetime elision rules make that lifetime be 'static. That's why you have an error: you're trying to put a Bytes<'a> in a place where 'static is required.
In order to allow your boxed iterator to borrow, you must define the types and traits to have a lifetime.
use core::iter::Peekable;
pub struct UTF8Chars<'a> {
bytes: Peekable<Box<dyn Iterator<Item = u8> + 'a>>,
}
trait ToUTF8Chars<'a> {
fn utf8_chars(self) -> UTF8Chars<'a>;
}
impl<'a> ToUTF8Chars<'a> for &'a str {
fn utf8_chars(self) -> UTF8Chars<'a> {
let bytes: Box<dyn Iterator<Item = u8> + 'a> = Box::new(self.bytes());
UTF8Chars {
bytes: bytes.peekable(),
}
}
}
If you don't want to add a lifetime, then you must only use owning iterators (e.g. String::into_bytes(s).into_iter()). With the lifetime, you can use both owning and borrowing iterators.
The issue is that dyn Trait types are actually dyn Trait + 'static by default, which means they're not allowed to borrow any data. That's a problem for you because the iterator returned by calling bytes() on a &'a str borrows from that str and thus cannot outlive 'a. But 'a doesn't outlive 'static so you can't make a dyn Iterator + 'static from it.
As you might have guessed, the solution here is adding some more general lifetime bounds, first to the struct:
pub struct UTF8Chars<'a> {
// ^^^^ now generic over 'a
bytes: Peekable<Box<dyn Iterator<Item = u8> + 'a>>,
// ------------------------^^^^
// the iterator is now allowed to borrow data for 'a
}
Then to the trait:
trait ToUTF8Chars {
fn utf8_chars<'a>(self) -> UTF8Chars<'a> where Self: 'a;
// ^^^^ also generic over 'a ^^^^^^^^ self can borrow data for 'a
}
Depending on your exact use case, using a borrowed receiver might be nicer, though:
trait ToUTF8Chars {
fn utf8_chars<'a>(&'a self) -> UTF8Chars<'a>;
// ^^^^ just borrow `self` for 'a
}
I'm sure there's a cases where these two aren't the same (object safety, probably?) but I can't pin point a specific situation off the top of my head.
And finally the implementation:
impl<'b> ToUTF8Chars for &'b str {
fn utf8_chars<'a>(self) -> UTF8Chars<'a> where Self: 'a {
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
UTF8Chars { bytes: bytes.peekable() }
}
}
or
impl ToUTF8Chars for str {
fn utf8_chars<'a>(&'a str) -> UTF8Chars<'a> {
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
UTF8Chars { bytes: bytes.peekable() }
}
}
for the alternative version of ToUTF8Chars.

Explicit lifetime for Vec to slice conversation

I want a callback on changes inside a list, so I created simple example:
struct Foo;
struct FooList {
list: Vec<Foo>,
on_change_cb: Vec<Box<FnMut(& mut [Foo])>>,
}
impl FooList {
/*
pub fn register_on_change_cb2<F>(&mut self, cb: F) where F: FnMut(&mut [Foo]) {
self.on_change_cb.push(Box::new(cb));
}*/
pub fn register_on_change_cb(&mut self, cb: Box<FnMut(&mut [Foo])>) {
self.on_change_cb.push(cb);
}
pub fn push(&mut self, foo: Foo) {
self.list.push(foo);
self.on_change();
}
fn on_change(&mut self) {
for cb in &mut self.on_change_cb {
cb(&mut self.list);
}
}
}
I don't give any explicit hint to the compiler about lifetimes here: Vec<Box<FnMut(& mut [Foo])>>, so what lifetimes will the compiler use here? If I change the code like this:
struct FooList<'a> {
list: Vec<Foo>,
on_change_cb: Vec<Box<FnMut(&'a mut [Foo])>>,
}
impl<'a> FooList<'a> {
I get a compile time error:
error[E0495]: cannot infer an appropriate lifetime for borrow
expression due to conflicting requirements
How can I explicitly set the lifetimes in some way such that the lifetime of & mut [Foo] for the callback is less than, but not equal to the lifetime of the whole FooList object?
I have commented register_on_change_cb2, I want to allow calling register_on_change_cb without usage of Box::new but failed. If you uncomment register_on_change_cb2, you get the error:
error[E0310]: the parameter type F may not live long enough
How can I fix this error without the requirement of a 'static lifetime for callback? I just want to call Box::new on my side.
I'm going to try to answer your questions 1 and 3, because question 2 is either redundant or orthogonal to the others, and I can't tell what you really want to achieve by it. Perhaps it deserves a question of its own.
If you have a function that takes a reference, but it doesn't need any lifetime information about the reference, it must be able to accept a reference of any lifetime. Here's the explicit syntax for that (this is what the compiler infers from the code you wrote):
on_change_cb: Vec<Box<for<'b> FnMut(&'b mut [Foo])>>,
This is called a higher ranked trait bound or HRTB for short. They're mostly useful for the Fn traits, which is why they exist.
If the type of on_change_cb is Vec<Box<FnMut(&mut [Foo])>>, which doesn't carry any lifetime information, then it must not contain any references (except 'static references). You need to say that the type implementing FnMut may also contain (non-'static) references, as long as they outlive some lifetime 'a:
struct FooList<'a> {
list: Vec<Foo>,
on_change_cb: Vec<Box<FnMut(&mut [Foo]) + 'a>>,
}
This reads something like: "For each FooList object, there is a lifetime 'a such that every callback in the FooList contains only references that live for at least 'a." This interpretation may make it easier to write the prototype for register_on_change_cb2: it takes a callback that also contains only references that live for at least 'a.
impl<'a> FooList<'a> {
pub fn register_on_change_cb2<F>(&mut self, cb: F)
where F: FnMut(&mut [Foo]) + 'a
{
self.on_change_cb.push(Box::new(cb));
}
(I think I have the variance of 'a correct now -- a previous version of this answer had it wrong.)
The 'a lifetime lets the compiler guarantee that you never put a callback in the Box (and therefore the Vec) unless it lasts at least as long as the FooList itself. This is important because closures can capture references to values in the enclosing scope, as in the following code (playground link):
let longlived = String::from("hello");
let mut list = FooList {
list: Vec::new(),
on_change_cb: Vec::new(),
};
list.register_on_change_cb2(|_| println!("{}", longlived)); // ok
let shortlived = String::from("hello");
list.register_on_change_cb2(|_| println!("{}", shortlived)); // `shortlived` does not live long enough
list.push(Foo);
In this example, you can't insert the closure that captures shortlived because it doesn't outlive the (inferred) lifetime 'a. But you can insert the closure that captures longlived, because the compiler can infer a lifetime 'a that satisfies both constraints:
'a must outlive list, because list is of type FooList<'a>.
longlived must outlive 'a, because |_| println!("{}", longlived), which borrows longlived, is bounded by 'a in the call to register_on_change_cb2.
If you want to say that the callbacks don't borrow anything by-reference, the 'a lifetime is unnecessary, and in that case you could just add the 'static bound that the compiler suggests:
pub fn register_on_change_cb2<F>(&mut self, cb: F)
where F: FnMut(&mut [Foo]) + 'static

Confusing error in Rust with trait object lifetime

Can anyone tell what the problem is with the following code? The compiler is complaining about lifetimes, but the error message makes absolutely no sense. I've tried everything I could think of, but nothing seems to help.
use std::borrow::BorrowMut;
trait Trait<'a> {
fn accept(&mut self, &'a u8);
}
struct Impl<'a>{
myref: Option<&'a u8>,
}
impl<'a> Trait<'a> for Impl<'a> {
fn accept(&mut self, inp: &'a u8) { self.myref = Some(inp); }
}
fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl{myref: None})
}
fn user<'a>(obj: &mut Trait<'a>) {}
fn parent<'a>(x: &'a u8) {
let mut pool = new();
user(pool.borrow_mut());
}
The compiler error is
error: `pool` does not live long enough
--> src/wtf.rs:22:10
|
22 | user(pool.borrow_mut());
| ^^^^ does not live long enough
23 | }
| - borrowed value dropped before borrower
|
= note: values in a scope are dropped in the opposite order they are created
Which makes absolutely no sense. How is the borrower outliving anything? I'm not even using the borrowed value!
Ok, this does make sense, but it's hard to see due to lifetime elision. So, here's your code with all the lifetimes written out explicitly, and with irrelevant details culled:
use std::borrow::BorrowMut;
trait Trait<'a> {}
struct Impl<'a> {
myref: Option<&'a u8>,
}
impl<'a> Trait<'a> for Impl<'a> {}
fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl { myref: None })
}
fn user<'a, 'b>(obj: &'b mut (Trait<'a> + 'b)) {}
fn parent() {
/* 'i: */ let mut pool/*: Box<Trait<'x> + 'x>*/ = new();
/* 'j: */ let pool_ref/*: &'i mut Box<Trait<'x> + 'x>*/ = &mut pool;
/* BorrowMut<T>::borrow_mut<'d>(&'d mut Self) -> &'d mut T */
/* 'k: */ let pool_borrow/*: &'i mut (Trait<'x> + 'x)*/ = Box::borrow_mut(pool_ref);
user(pool_borrow);
}
Now, from the perspective of the last line of parent, we can work out the following equivalences by just reading the definition of user and substituting the lifetimes we have in parent:
'a = 'x
'b = 'i
'b = 'x
Furthermore, this lets us conclude that:
'x = 'i
This is the problem. Because of the way you've defined user, you've put yourself in a situation where the lifetime of the pool_ref borrow (which is equal to the lifetime of the pool storage location you're borrowing from) must be the same as the lifetime 'x being used in the thing being stored in pool.
It's a bit like the Box being able to have a pointer to itself before it exists, which doesn't make any sense.
Either way, the fix is simple. Change user to actually have the correct type:
fn user<'a, 'b>(obj: &'b mut (Trait<'a> + 'a)) {}
This matches the type produced by new. Alternately, just don't use borrow_mut:
user(&mut *pool)
This works because it is "re-borrowing". Calling borrow_mut translates the lifetimes more or less directly, but re-borrowing allows the compiler to narrow the borrows to shorter lifetimes. To put it another way, explicitly calling borrow_mut doesn't allow the compiler enough freedom to "fudge" the lifetimes to make them all line up, re-borrowing does.
As a quick aside:
I'm not even using the borrowed value!
Irrelevant. Rust does type- and lifetime-checking entirely locally. It never looks at the body of another function to see what it's doing; it goes on the interface alone. The compiler neither checks, nor cares, what you're doing inside a different function.
Note that there's more to the error message:
error: `pool` does not live long enough
--> src/main.rs:25:10
|>
25 |> user(pool.borrow_mut());
|> ^^^^
note: reference must be valid for the block at 23:25...
--> src/main.rs:23:26
|>
23 |> fn parent<'a>(x: &'a u8) {
|> ^
note: ...but borrowed value is only valid for the block suffix following statement 0 at 24:25
--> src/main.rs:24:26
|>
24 |> let mut pool = new();
|> ^
Let's look at user:
fn user<'a>(obj: &mut Trait<'a>) {}
This says that it will accept a mutable reference (with an unnamed lifetime) to a trait object parameterized with the lifetime 'a.
Turning to new, I'd say the method is highly suspicious:
fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl { myref: None })
}
This says that it will return a boxed trait object with whatever lifetime the caller specifies. That basically never makes sense.
All that said, I'm not clear why the code chooses to use borrow_mut. I would have written that more directly:
user(&mut *pool);
This dereferences the Box<Trait> to get a Trait, then takes a mutable reference, yielding &mut Trait, which compiles.
I cannot currently explain why BorrowMut differs in behavior.
I'm not sure why this error happens, but I can give solutions!
First, it seems that using borrow_mut unnecessarily restricts the lifetime of the returned reference. Using operators to create the reference solves the error.
fn parent() {
let mut pool = new();
user(&mut *pool);
}
However, if we don't do that, we can solve the error by adding a lifetime bound to the Trait object in user's obj argument.
fn user<'a>(obj: &mut (Trait<'a> + 'a)) {}

How can I correct "cannot infer an appropriate lifetime" without editing function signature?

Background: I'm creating an iterator that returns a reference to a slice &[T], but the data vector needs to remain immutable. The iterator cannot modify the original data, but must return the same slice pointer repeatedly after it has modified it. I've considered having my iterator own a Vec<T>, but I would like to avoid that (and it didn't seem to work). I avoid allocations since I plan to use it mostly in realtime audio and allocations could potentially block. Code:
pub struct Windower<'a, 'b, T: 'a + 'b> {
window_type: WindowType,
hop_size: usize,
bin_size: usize,
current_index: usize,
data: &'a [T],
out_data: &'b mut [T]
}
impl<'a, 'b, T: Float + FromPrimitive> Iterator for Windower<'a, 'b, T> {
type Item = &'b [T];
fn next(&mut self) -> Option<Self::Item> {
if self.current_index < (self.len() - 1) {
let start = self.current_index * self.hop_size;
let end = start + self.bin_size;
self.current_index += 1;
let window = self.window();
let data_iter = self.data[start..end].iter();
for &mut v in self.out_data {
let val: T = window.next().unwrap() *
*data_iter.next().unwrap();
v = val;
}
Some(self.out_data)
} else {
None
}
}
}
Returns the error:
src/waves.rs:160:18: 160:31 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements [E0495]
src/waves.rs:160 Some(self.out_data)
^~~~~~~~~~~~~
src/waves.rs:146:5: 164:6 help: consider using an explicit lifetime parameter as shown: fn next(&'b mut self) -> Option<Self::Item>
I cannot figure out how to fix this. I can't make the change suggested, because the trait implementation for Iterator does not have an explicit lifetime parameter.
Rust prevents you from having more than one alias to an object if one of them is a mutable alias.
Here, Windower::out_data is a mutable alias to some slice, and you're trying to return an immutable alias to the same data from your next method. In order for this to be safe, Rust must prevent you from being able to use Windower::out_data for as long as the slice returned by next is in scope. This means that the signature fn next(&'b mut self) -> Option<Self::Item> is indeed required, which means you simply cannot implement Iterator with your current implementation.

Expanding Rust Lifetime

I have a bit of code that I'm fighting with. It's a little helper function that should return a Vec<&str> to the calling function. I can't seem to get the lifetime right, though.
Here is the code snippet:
fn take_symbol<'a>(ch: &'a str, current: &'a mut String) -> &'a mut TokenList<'a> {
let out = TokenList::<'a>::new();
out.push(current.as_str());
out.push(ch);
*current = String::new();
&mut out
}
The compiler is telling me: error: 'out' does not live long enough and that the reference must be valid for the lifetime of 'a, but it looks to me like it is defined for 'a.
I have also tried changing it to:
let out = &mut TokenList::<'a>::new();
which doesn't change any of the error messages. Or:
let out = &'a mut TokenList::<'a>::new();
which the compiler doesn't like at all.
How do I define out to have a lifetime of 'a?
For further details, here is my definition of TokenList:
pub type Token<'a> = &'a str;
pub type TokenList<'a> = Vec<Token<'a>>;
The lifetime of out is not 'a, since out is destroyed at the end of the function. Rust will not allow you to return a reference to it (it would allow accessing freed memory!).
Try changing your function to the following:
fn take_symbol<'a>(ch: &'a str, current: &'a mut String) -> TokenList<'a> {
let out = TokenList::<'a>::new();
out.push(current.as_str());
out.push(ch);
*current = String::new();
out
}
This way you will pass the ownership of out to the caller and it will live long enough.

Resources