Closure which captures outer scope as field of struct in Rust - rust

I am new to Rust and I am trying to create combinator parser in it. Here is the code:
enum Parser<T: Copy + Eq> {
Ok,
Eof,
Satisfy { predicate: Box<dyn Fn(&T) -> bool> },
Element { elem : T }
}
impl<T: Copy + Eq> Parser<T> {
fn parse<'a, P>(&self, input: &'a [T]) -> Option<(&'a [T], P)>
where
P: Default,
T: Into<P>
{
match self {
Parser::Ok => Some((input, P::default())),
Parser::Eof => match input {
[] => None,
_ => Some((input, P::default())),
},
Parser::Satisfy { predicate } => match input {
[] => None,
[x, rest # ..] => {
if predicate(x) {
Some((rest, T::into(*x)))
} else {
None
}
}
},
Parser::Element { elem } => {
let to_match = *elem;
Parser::Satisfy { predicate: Box::new(move|x| *x == to_match) }.parse(input)
}
}
}
}
Parser::Ok, Parser::Eof and Parser::Satisfy are working fine but I struggled with realization of Parser::Element (which must much only exact element). I want to realize method parse for it with creation of Parser::Satisfy with predicate of eq between argument x and given elem. But I run into this error:
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:32:46
|
32 | Parser::Satisfy { predicate: Box::new(move|x| *x == to_match) }.parse(input)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
8 | impl<T: Copy + Eq + 'static> Parser<T> {
| +++++++++
I feel there is some problem with lifetimes but I do not know how to fix it.

dyn Trait contains things. These things may have lifetimes. Therefore, dyn Trait also has a lifetime.
This lifetime, like functions' lifetimes, can be elided. The full rules are somewhat complicated, but when in an ADT, the lifetime is assumed to be 'static. You can specify another lifetime with dyn Trait + 'lifetime.
Thus, the Box<dyn Fn(&T) -> bool> in your enum is actually Box<dyn Fn(&T) -> bool + 'static>.
But the problem is that the function you assign into it captures to_match, of type T. And type T may contain a non-'static lifetime. For example, it may contain &'non_static str. This is the error.
This has two possible solutions.
Either accept that and require T to be 'static:
impl<T: Copy + Eq + 'static> Parser<T> {
Or allow non-'static lifetime for the function:
enum Parser<'a, T: Copy + Eq> {
Ok,
Eof,
Satisfy { predicate: Box<dyn Fn(&T) -> bool + 'a> },
Element { elem : T }
}
impl<T: Copy + Eq> Parser<'_, T> {

Related

How to create a recursive queue?

I am trying to implement a recursive queue using the trait Element<T> as a container for all the functions of the different nodes of the queue and two structs implementing it called Node<T> and End.
The Node<T> struct is supposed to handle all the functionality within the queue itself and the End struct's purpose is to deal with the case of the last node.
I've got the following code:
trait Element<T> {
fn append_item(self, item: T) -> Node<T>;
}
struct Node<T> {
data: T,
successor: Box<dyn Element<T>>
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self, item: T) -> Node<T> {
self.successor = Box::new(self.successor.append_item(item));
self
}
}
struct End;
impl<T> Element<T> for End {
fn append_item(self, item: T) -> Node<T> {
Node { data: item, successor: Box::new(self) }
}
}
The problem is, that I get two errors:
Cannot move a value of type dyn Element<T>
The parameter type T may not live long enough
both on the same line in Node::append_item.
Now, I get why the first error occurs (because the size of dyn Element<T> cannot be statically determined) but I don't know how to work around it and I have no idea why the second error occurs.
error[E0161]: cannot move a value of type `dyn Element<T>`
--> src/lib.rs:12:35
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the size of `dyn Element<T>` cannot be statically determined
The issue here is that fn append_item(self, item: T) takes self by value, but in this case self has type dyn Element<T>, which is unsized and can therefore never be passed by value.
The easiest solution here is to just take self: Box<Self> instead. This means that this method is defined on a Box<E> instead of directlThis will work perfectly fine with trait objects like dyn Element<T>, and it does not require the type to be sized.
(Additionally, in the updated code below, I've changed the return type to Box<Node<T>> for convenience, but this is not required per se, just a bit more convenient.)
trait Element<T> {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>>;
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self: Box<Self>, item: T) -> Box<Node<T>> {
self.successor = self.successor.append_item(item);
self
}
}
impl<T> Element<T> for End {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>> {
Box::new(Node { data: item, successor: self })
}
}
[Playground link]
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:12:26
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
The issue here is that dyn Trait has an implicit lifetime. In reality, it's dyn '_ + Trait. What exactly that lifetime is depends on the context, and you can read the exact rules in the Rust reference, but if neither the containing type nor the trait itself has any references, then the lifetime will always be 'static.
This is the case with Box<dyn Element<T>>, which really is Box<dyn 'static + Element<T>>. In other words, whatever type is contained by the Box must have a 'static lifetime. For this to be the case for Node<T>, it must also be that T has a 'static lifetime.
This is easy to fix, though: just follow the compiler's suggestion to add a T: 'static bound:
impl<T: 'static> Element<T> for Node<T> {
// ^^^^^^^^^
// ...
}
[Playground link)
Frxstrem already elaborated how to get around the need to move by using Box<Self> as receiver. If you need more flexibility in the parameter type (i.e. be able to hold on to references as well as owned types) instead of requiring T: 'static you can introduce a named lifetime:
trait Element<'a, T: 'a> {
fn append_item(self: Box<Self>, item: T) -> Node<'a, T>;
}
struct Node<'a, T: 'a> {
data: T,
successor: Box<dyn Element<'a, T> + 'a>,
}
impl<'a, T: 'a> Element<'a, T> for Node<'a, T> {
fn append_item(self: Box<Self>, new_data: T) -> Node<'a, T> {
Node {
successor: Box::new(self.successor.append_item(new_data)),
..*self
}
}
}
struct End;
impl<'a, T: 'a> Element<'a, T> for End {
fn append_item(self: Box<Self>, data: T) -> Node<'a, T> {
Node {
data,
successor: self,
}
}
}

Lifetime of a closure stored in a struct

I tried to apply the answers of this question to my situation, but failed to do so.
I assume, what I try to do is much simpler.
Before I explain, first a bit of code:
type Coord = (usize, usize);
pub struct SquareIterator {
upper_bounds: Coord,
direction: Coord,
predicate: Box<dyn Fn(Coord) -> bool>,
current: Coord,
}
impl SquareIterator {
pub fn new<P>(
start_square: Coord,
direction: Coord,
board_size: Coord,
predicate: P,
) -> SquareIterator
where
P: Fn(Coord) -> bool,
{
SquareIterator {
upper_bounds: board_size,
direction,
predicate: Box::new(predicate),
current: start_square,
}
}
}
impl Iterator for SquareIterator {
type Item = Coord;
fn next(&mut self) -> Option<Self::Item> {
let next = (
self.current.0 + self.direction.0,
self.current.1 + self.direction.1,
);
if next.0 >= self.upper_bounds.0 || next.1 >= self.upper_bounds.1 {
None
} else if (self.predicate)(next) {
self.current = next;
Some(self.current)
} else {
None
}
}
}
It is about the predicate closure, which is supposed to live as long as the containing struct SquareIterator lives.
Application code, using this looks along the lines of:
struct Board {
// ... some members ...
}
impl Board {
pub fn queen_moves(&self, queen_coord: (u8, Coord)) -> SquareIterator {
SquareIterator::new(queen_coord.1, (0, 1), self.board_size(), |coord| {
self.squares[coord.1][coord.0] == sv::EMPTY
})
}
}
After fiddling for two hours, reading up the lifetimes chapter in the rust book a couple of times, looking at the above mentioned other stackoverflow question, I am still at a loss as to how to teach Rust, that my closure will be alive as long as the iterator...
While I am aware, that there is lifetime stuff missing, the current ccode yields the error:
> error[E0310]: the parameter type `P` may not live long enough
--> amazons-engine/src/lib.rs:33:18
|
33 | predicate: Box::new(predicate),
| ^^^^^^^^^^^^^^^^^^^ ...so that the type `P` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
29 | P: Fn(Coord) -> bool + 'static, {
| +++++++++
For more information about this error, try `rustc --explain E0310`.
So, how to do it?
You need to tell the compiler that SquareIterator might be bound to a specific lifetime. Closures that borrow from their environment aren't 'static, but a struct without a lifetime parameter is assumed to reference nothing (e.g. be 'static) itself. This makes your closure that borrows self incompatible with the implied-static lifetime.
Step one is to tell the compiler that SquareIterator might refer to an external lifetime, and that this lifetime belongs to the closure type:
pub struct SquareIterator<'a> {
upper_bounds: Coord,
direction: Coord,
predicate: Box<dyn 'a + Fn(Coord) -> bool>,
current: Coord,
}
Step two is to adjust the constructor function similarly, which binds together the lifetime of the supplied closure with that of the returned SquareIterator, allowing the compiler to infer 'a for you:
impl SquareIterator<'_> {
pub fn new<'a, P>(
start_square: Coord,
direction: Coord,
board_size: Coord,
predicate: P,
) -> SquareIterator<'a>
where
P: 'a + Fn(Coord) -> bool,
{ ... }
}
Finally, the impl Iterator block needs to include a lifetime, but we can use the "please infer me" lifetime '_ since the implementation doesn't depend on it:
impl Iterator for SquareIterator<'_> { ... }
(Playground, which has some placeholder types/methods to allow it to compile.)

How to find generic bounds for producer that creates objects with trait-lifetime bounds

I have reduced my actual code to this minimal example:
trait Producer<P> where P: Something {
fn produce(&self) -> Box<P>;
}
struct P1 {}
impl Producer<B1> for P1 {
fn produce(&self) -> Box<B1> {
Box::new(B1 {})
}
}
trait Something {}
trait Borrower<'b> {
type B: std::fmt::Display;
fn borrow(&'b self) -> Self::B;
}
struct B1 {}
impl Something for B1 {}
impl<'b> Borrower<'b> for B1 {
type B = Borrowing1<'b>;
fn borrow(&'b self) -> Self::B {
Borrowing1 { _b: &self }
}
}
struct Borrowing1<'b> {
_b: &'b B1,
}
impl<'b> std::fmt::Display for Borrowing1<'b> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Borrowing1")
}
}
fn perform<'b, P, B>(producer: P) where P: Producer<B>, B: Something + Borrower<'b> + 'static {
for _ in 0..1 {
let b = producer.produce();
let s = b.borrow().to_string();
eprintln!("{}", s);
}
}
fn main() {
let p1 = P1 {};
perform(p1);
}
I have a Producer type that creates Something. And that something can implement Borrower<'b>, which introduces a lifetime. Then, I want to restrict a function perform to receive producers that produce Something with the trait Borrower<'b>. However, since I can't prevent introducing a lifetime in perform the function thinks that all produced items must live for the entire function execution. Actually, they are static objects that just implement Borrower<'b>. But I struggle finding the correct bounds.
The error message reflects that:
error[E0597]: `*b` does not live long enough
--> src/main.rs:46:17
|
43 | fn perform<'b, P, B>(producer: P) where P: Producer<B>, B: Something + Borrower<'b> + 'static {
| -- lifetime `'b` defined here
...
46 | let s = b.borrow().to_string();
| ^---------
| |
| borrowed value does not live long enough
| argument requires that `*b` is borrowed for `'b`
47 | eprintln!("{}", s);
48 | }
| - `*b` dropped here while still borrowed
Maybe you can help me with that.
This can be solved using higher-rank trait bounds:
You don't have to pass a lifetime to function here. Instead you need to define a lifetime on the go when borrow() is called. Following should solve the issue:
fn perform<P, B>(producer: P)
where
P: Producer<B>,
for<'b> B: Something + Borrower<'b> + 'static,
{
for _ in 0..1 {
let b = producer.produce();
let u = b.borrow();
let s = u.to_string();
eprintln!("{}", s);
}
}
Playground
Higher-rank trait bounds are explained pretty nicely here: How does for<> syntax differ from a regular lifetime bound?

Lifetime parameter for `Self` in trait signature

Consider this simple protocol implementation:
#[derive(PartialEq, Debug)]
enum Req<'a> {
InputData(&'a [u8]),
Stop,
}
impl<'a> Req<'a> {
fn decode(packet: &'a [u8]) -> Result<Req<'a>, String> {
match packet.first() {
Some(&0x01) => Ok(Req::InputData(&packet[1..])),
Some(&0x02) => Ok(Req::Stop),
_ => Err(format!("invalid request: {:?}", packet)),
}
}
}
#[derive(PartialEq, Debug)]
enum Rep<'a> {
OutputData(&'a [u8]),
StopAck,
}
impl<'a> Rep<'a> {
fn decode(packet: &'a [u8]) -> Result<Rep<'a>, String> {
match packet.first() {
Some(&0x01) => Ok(Rep::OutputData(&packet[1..])),
Some(&0x02) => Ok(Rep::StopAck),
_ => Err(format!("invalid reply: {:?}", packet)),
}
}
}
fn assert_req(packet: Vec<u8>, sample: Req) {
assert_eq!(Req::decode(&packet), Ok(sample));
}
fn assert_rep(packet: Vec<u8>, sample: Rep) {
assert_eq!(Rep::decode(&packet), Ok(sample));
}
fn main() {
assert_req(vec![1, 2, 3], Req::InputData(&[2, 3]));
assert_req(vec![2], Req::Stop);
assert_rep(vec![1, 2, 3], Rep::OutputData(&[2, 3]));
assert_rep(vec![2], Rep::StopAck);
}
playground
This works, but the two functions assert_req and assert_rep have identical code with only a difference in types. It is a good idea to write one generic assert_packet:
trait Decode<'a>: Sized {
fn decode(packet: &'a [u8]) -> Result<Self, String>;
}
#[derive(PartialEq, Debug)]
enum Req<'a> {
InputData(&'a [u8]),
Stop,
}
impl<'a> Decode<'a> for Req<'a> {
fn decode(packet: &'a [u8]) -> Result<Req<'a>, String> {
match packet.first() {
Some(&0x01) => Ok(Req::InputData(&packet[1..])),
Some(&0x02) => Ok(Req::Stop),
_ => Err(format!("invalid request: {:?}", packet)),
}
}
}
#[derive(PartialEq, Debug)]
enum Rep<'a> {
OutputData(&'a [u8]),
StopAck,
}
impl<'a> Decode<'a> for Rep<'a> {
fn decode(packet: &'a [u8]) -> Result<Rep<'a>, String> {
match packet.first() {
Some(&0x01) => Ok(Rep::OutputData(&packet[1..])),
Some(&0x02) => Ok(Rep::StopAck),
_ => Err(format!("invalid reply: {:?}", packet)),
}
}
}
fn assert_packet<'a, T>(packet: Vec<u8>, sample: T)
where
T: Decode<'a> + PartialEq + std::fmt::Debug,
{
assert_eq!(T::decode(&packet), Ok(sample));
}
fn main() {
assert_packet(vec![1, 2, 3], Req::InputData(&[2, 3]));
assert_packet(vec![2], Req::Stop);
assert_packet(vec![1, 2, 3], Rep::OutputData(&[2, 3]));
assert_packet(vec![2], Rep::StopAck);
}
playground
However, this triggers a "does not live long enough" error:
error[E0597]: `packet` does not live long enough
--> src/main.rs:41:27
|
41 | assert_eq!(T::decode(&packet), Ok(sample));
| ^^^^^^ does not live long enough
42 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 37:1...
--> src/main.rs:37:1
|
37 | / fn assert_packet<'a, T>(packet: Vec<u8>, sample: T)
38 | | where
39 | | T: Decode<'a> + PartialEq + std::fmt::Debug,
40 | | {
41 | | assert_eq!(T::decode(&packet), Ok(sample));
42 | | }
| |_^
If I understand correctly, the problem is in the function signature:
fn assert_packet<'a, T>(packet: Vec<u8>, sample: T)
where
T: Decode<'a>
Here, packet is destroyed when the function returns, but the user-provided 'a lifetime parameter says that the lifetime should end somewhere outside the assert_packet function. Is there any right solution? How should the signature look? Maybe higher rank trait bounds could help here?
Why does this compile:
fn assert_req(packet: Vec<u8>, sample: Req) {
assert_eq!(Req::decode(&packet), Ok(sample));
}
while this doesn't?
fn assert_packet<'a, T>(packet: Vec<u8>, sample: T) where T: Decode<'a> + PartialEq + std::fmt::Debug {
assert_eq!(T::decode(&packet), Ok(sample));
}
The difference is that in the first version, the two textual occurrences of Req name two different instances of the Req<'a> struct, with two different lifetimes. The first occurrence, on the sample parameter, is specialized with a lifetime parameter received by the assert_req function. The second occurrence, used to invoke decode, is specialized with the lifetime of the packet parameter itself (which ceases to exist as soon as the function returns). This means that the two arguments to assert_eq! don't have the same type; yet, it compiles because Req<'a> can be coerced to a Req<'b> where 'b is a shorter lifetime than 'a (Req<'a> is a subtype of Req<'b>).
On the other hand, in the second version, both occurrences of T must represent the exact same type. Lifetime parameters are always assumed to represent lifetimes that are longer than the function call, so it's an error to invoke T::decode with a lifetime that is shorter.
Here's a shorter function that exhibits the same problem:
fn decode_packet<'a, T>(packet: Vec<u8>) where T: Decode<'a> {
T::decode(&packet);
}
This function fails to compile:
<anon>:38:16: 38:22 error: `packet` does not live long enough
<anon>:38 T::decode(&packet);
^~~~~~
It's possible to use higher rank trait bounds on this function to make it compile:
fn decode_packet<T>(packet: Vec<u8>) where for<'a> T: Decode<'a> {
T::decode(&packet);
}
However, now we have another problem: we can't invoke this function! If we try to invoke it like this:
fn main() {
decode_packet(vec![1, 2, 3]);
}
We get this error:
<anon>:55:5: 55:18 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
<anon>:55 decode_packet(vec![1, 2, 3]);
^~~~~~~~~~~~~
That's because we didn't specify which implementation of Decode we want to use, and there are no parameters the compiler can use to infer this information.
What if we specify an implementation?
fn main() {
decode_packet::<Req>(vec![1, 2, 3]);
}
We get this error:
<anon>:55:5: 55:25 error: the trait `for<'a> Decode<'a>` is not implemented for the type `Req<'_>` [E0277]
<anon>:55 decode_packet::<Req>(vec![1, 2, 3]);
^~~~~~~~~~~~~~~~~~~~
That doesn't work, because the Req we wrote is actually interpreted as Req<'_>, where '_ is a lifetime inferred by the compiler. This doesn't implement Decode for all possible lifetimes, only for one particular lifetime.
In order to be able to implement your desired function, Rust would have to support higher kinded types. It would then be possible to define a type constructor parameter (instead of a type parameter) on the function. For instance, you'd be able to pass Req or Rep as a type constructor requiring a lifetime parameter to produce a specific Req<'a> type.
It works correctly if you link the lifetimes involved to the input which you'll be referencing, e.g.
fn assert_packet<'a, T>(packet: &'a [u8], sample: T) where T: Decode<'a> ..
(You'll also need to update the tests to pass borrows rather than owned Vecs.)

Bounds on associated types but 'error: the type of this value must be known in this context'

The following
use std::borrow::Borrow;
trait DictLike<'a> {
type Label: Eq + 'a;
type ItemsIterator: Iterator<Item=(&'a Self::Label, &'a DictLike<'a>)> + 'a;
fn items(&self) -> Self::ItemsIterator;
fn get<Q: ?Sized + Eq>(&self, key: &Q) -> Option<&'a DictLike<'a>>
where Self::Label: Borrow<Q> {
for (k,v) in self.items() {
if k.borrow().eq(key) {
return Some(v);
}
}
None
}
}
errors out as
lib.rs:12:16: 12:26 error: the type of this value must be known in this context
lib.rs:12 if k.borrow().eq(key) {
^~~~~~~~~~
Why? Doesn't ItemsIterator's type bound and the bound Self::Label: Borrow<Q> provide the necessary type information?
This seems like a bug: the <'a> in the trait declaration is seemingly causing the compiler to get confused, e.g.:
trait DictLike<'a> {
type ItemsIterator: Iterator<Item=u8>;
fn items(&self) -> Self::ItemsIterator;
fn get(&self) {
for k in self.items() {}
}
}
<anon>:7:13: 7:14 error: unable to infer enough type information about `_`; type annotations required [E0282]
<anon>:7 for k in self.items() {}
^
Removing the 'a allows that code to compile. I've filed #24338 about this.
Fortunately, there is a work around: this seems to only happen when the code is inside the default method, and moving the actual implementation to an external function works fine:
use std::borrow::Borrow;
trait DictLike<'a> {
type Label: Eq + 'a;
type ItemsIterator: Iterator<Item=(&'a Self::Label, &'a DictLike<'a>)> + 'a;
fn items(&self) -> Self::ItemsIterator;
fn get<Q: ?Sized + Eq>(&self, key: &Q) -> Option<&'a DictLike<'a>>
where Self::Label: Borrow<Q> {
get(self, key)
}
}
fn get<'a, X: ?Sized + DictLike<'a>, Q: ?Sized + Eq>(x: &X, key: &Q) -> Option<&'a DictLike<'a>>
where X::Label: Borrow<Q> {
for (k,v) in x.items() {
if k.borrow() == key {
return Some(v);
}
}
None
}
This is functionally no different to the original code, except for the fact that it compiles. (I took the liberty of switching the .eq call to the == operator, which is nicer sugar for the method call.)
Also, if you're feeling like experimenting with iterators a little more, one could write get as
x.items()
.find(|&(k,_)| k.borrow() == key)
.map(|(_, v)| v)
Using Iterator::find and Option::map.

Resources