inside thread::spawn all the variable must be 'static or be the real owner (not owner of refence etc...). when function return T generics in thread::spawn rust compile error T must have 'static life
I have mspc::Receiver who receive a function with genetic who return T Like this
thread::spawn(move || {
let rece: Box<dyn FnOnce() -> T + Send + 'static> = rece.lock().unwrap().recv().unwrap();
});
of course I can not do that because I don't have any trait of ownership of T or 'static lifetime.
equation : how can I implant T (generic\variable like usize or f64) as ownership and how I can I Implant T That can be 'static or ownership
Related
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.
When I try to store closures to a HashMap, I come across a lifetime bound requirement reported by the compiler. It seems like an inconsistent requirement.
struct NoBox<C: Fn() -> ()>(HashMap<String, C>);
impl<C> NoBox<C>
where
C: Fn() -> (),
{
fn new() -> NoBox<C> {
NoBox(HashMap::new())
}
fn add(&mut self, str: &str, closure: C) {
self.0.insert(str.to_string(), closure);
}
}
This is Ok. The compiler is happy with it. However, when I try to wrap the closure into a trait object and store it. The compiler imposes a 'static lifetime bound on it.
struct Boxed(HashMap<String, Box<dyn Fn() -> ()>>);
impl Boxed {
fn new() -> Boxed {
Boxed(HashMap::new())
}
fn add<C>(&mut self, str: &str, closure: C)
where
C: Fn() -> ()//add 'static here fix the error
{
self.0.insert(str.to_string(), Box::new(closure)); //error: type parameter C may not live long enough, consider adding 'static lifebound
}
}
According to the complain of the compiler, C may not live long enough. It makes sense to add a 'static bound to it.
But, why the first case without boxing doesn't have this requirement?
To my understanding, if C contains some reference to an early-dropped referent, then store it in NoBox would also cause the invalid-reference problem. For me, it seems like an inconsistency.
NoBox is not a problem because if the function contains a reference to the lifetime, the type will stay contain this lifetime because the function type needs to be specified explicitly.
For example, suppose we're storing a closure that captures something with lifetime 'a. Then the closure's struct will looks like (this is not how the compiler actually desugars closures but is enough for the example):
struct Closure<'a> {
captured: &'a i32,
}
And when specifying it in NoBox, the type will be NoBox<Closure<'a>>, and so we know it cannot outlive 'a. Note this type may never be actually explicitly specified - especially with closures - but the compiler's inferred type still have the lifetime in it.
With Boxed on the other hand, we erase this information, and thus may accidentally outlive 'a - because it does not appear on the type. So the compiler enforces it to be 'static, unless you explicitly specify otherwise:
struct Boxed<'a>(HashMap<String, Box<dyn Fn() + 'a>>);
I'm in a situation where I need to store away a function that implements a trait into a struct. Here is some reduced code
struct Node<T>{
compute_func: Box<dyn Fn(&[T]) -> T>
}
impl<T: Debug + 'static> OtherHoldingStruct<T> {
pub fn create_node<F: Fn(&[T]->T>(..., _compute_func: F) {
Node {
compute_function: Box::new(_compute_func),
//~~~~ the parameter type `impl Fn(&[T]) -> T` may not live long enough
//~~~~ ...so that the type `impl Fn(&[T]) -> T` will meet its required lifetime bounds rustc(E0310)
}
}
What I gather is that since I'm trying to accept a function type that takes a reference to a slice, the compiler is trying to create some assurances around how the lifetime of the reference to the slice will behave. What i'm not sure of is how to give it that ?
I considered adding a lifetime to create_node
impl<T: Debug + 'static> OtherHoldingStruct<T> {
pub fn create_node<'a, F: Fn(&'a [T]->T>(..., _compute_func: F) {
Node {
compute_function: Box::new(_compute_func),
//~~~~ expected a `std::ops::Fn<(&[T],)>` closure, found `impl Fn(&'a [T]) -> T`
}
}
which then seems to barf at not being able to match closures to the type.
The problem is not the slice reference — it's a lifetime requirement on the function type F itself. If you're going to store the function, then the function itself must be able to live for 'static (unless there's an explicitly permitted shorter lifetime).
The requirement actually in your code causing the compiler error appears because dyn Fn (or any other dyn) has an implicit + 'static bound if you don't specify a different lifetime. Thus, the bounds for F in create_node are Fn(&[T]) -> T but the bounds for compute_function are Fn(&[T]) -> T + 'static, creating the error you saw.
The fix is to add a 'static bound on F:
pub fn create_node<F: Fn(&[T]) -> T + 'static>(_compute_func: F) -> Node<T> {
// ^^^^^^^^^
This bound disallows passing, for example, a closure that captures a non-static reference, which has to be invalid anyway since Node could live indefinitely, unlike that reference.
I was writing some code where I want to use an iterator, or its reversed version depending on a flag, but the straightforward code gives an error
pub fn eggs<I,T>(iter:I)->Box<dyn Iterator<Item=T>>
where I:Iterator<Item=T>+DoubleEndedIterator
{
Box::new(iter.rev())
}
pub fn bacon<I,T>(iter:I, reverse:bool) -> Box<dyn Iterator<Item=T>>
where I:Iterator<Item=T>+DoubleEndedIterator
{
if reverse {
Box::new(iter.rev())
} else {
Box::new(iter)
}
}
fn main()
{
let pants:String = "pants".into();
eggs(pants.chars());
}
fails to compile:
error[E0310]: the parameter type `I` may not live long enough
--> src/main.rs:5:5
|
2 | pub fn eggs<I,T>(iter:I)->Box<dyn Iterator<Item=T>>
| - help: consider adding an explicit lifetime bound...: `I: 'static`
...
5 | Box::new(iter.rev())
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `Rev<I>` will meet its required lifetime bounds
With my limited understanding of Rust, I'm not sure where those lifetime bounds are coming from. There aren't any on the Iterator trait, or the Rev struct, and the parameter is being moved.
What is the proper way to declare these sorts of functions given that 'static isn't really an option.
rust playground
This doesn't have to do with .rev() at all, but with returning Box<dyn Iterator>:
// error[E0310]: the parameter type `I` may not live long enough
fn boxed_iter<I, T>(iter: I) -> Box<dyn Iterator<Item = T>>
// - help: consider adding an explicit lifetime bound...: `I: 'static`
where
I: Iterator<Item = T>,
{
Box::new(iter)
// ^^^^^^^^^^^^^^ ...so that the type `I` will meet its required lifetime bounds
}
The reason for this is that trait objects like Box<dyn Trait> have an implicit 'static lifetime if not specified. So when the compiler tries to cast Box<I> to Box<dyn Iterator>, it fails if I is does not also have a 'static lifetime. (There are some more specific rules if the trait contains lifetimes itself; you can read about those in more detail here.)
If you instead want a shorter lifetime, you need to specify it explicitly as Box<dyn 'a + Trait>. So for example:
fn boxed_iter<'a, I, T>(iter: I) -> Box<dyn 'a + Iterator<Item = T>>
where
I: 'a + Iterator<Item = T>,
{
Box::new(iter)
}
Frxstrem's answer is excellent. I just want to add that, if you know that the return value of your function has a specific concrete type, you can use the special impl trait syntax.
In the case of your eggs function, the return type is probably something like Rev<I>. That type, on its own, isn't very illuminating, but we know that such a type exists and the only thing we care about is that it's an iterator, so we can write
pub fn eggs<I,T>(iter:I) -> impl Iterator<Item=T> + DoubleEndedIterator
where I: Iterator<Item=T> + DoubleEndedIterator {
iter.rev()
}
Now the compiler still understands that there is a single concrete type and will act accordingly (no need to box the value or have dynamic dispatch), but we as the programmers still only have to care about the Iterator and DoubleEndedIterator aspects of it. Zero-cost abstraction at its finest.
Your bacon function can't benefit from this, as it could return either an I or a Rev<I> depending on input, so the dynamic dispatch is actually necessary. In that case, you'll need to follow Frxstrem's answer to correctly box your iterator.
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