How can I let one struct contains another struct and a value produced by that struct in Rust? - rust

Actually the lexer's get_next_token will return a Token which has no relation to the lexer.
But the get_next_token method would borrow "mut self", so the compiler kept yelling "cannot return value referencing function parameter lexer".
How can I deal with it???????
// in impl lexer
fn get_next_token(&mut self) -> Token {
let mut result = None;
while self.current_char != None {
match self.current_char {
// editing result
}
}
if let Some(token) = result {
token
} else {
Token::new(EOF, Nil)
}
}
struct Intepreter<'a> {
lexer: Lexer<'a>,
current_token: Token<'a>
}
impl<'a> Intepreter<'a> {
fn new(mut lexer: Lexer<'a>) -> Intepreter {
let current_token = lexer.get_next_token();
Intepreter {
lexer: lexer,
current_token // error!
}
}
}
error[E0515]: cannot return value referencing function parameter `lexer`
--> src\main.rs:134:9
|
133 | let current_token = lexer.get_next_token();
| ---------------------- `lexer` is borrowed here
134 | / Intepreter {
135 | | lexer: lexer,
136 | | current_token
137 | | }
| |_________^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `lexer` because it is borrowed
--> src\main.rs:135:20
|
131 | impl<'a> Intepreter<'a> {
| -- lifetime `'a` defined here
132 | fn new(mut lexer: Lexer<'a>) -> Intepreter {
133 | let current_token = lexer.get_next_token();
| ---------------------- borrow of `lexer` occurs here
134 | / Intepreter {
135 | | lexer: lexer,
| | ^^^^^ move out of `lexer` occurs here
136 | | current_token
137 | | }
| |_________- returning this value requires that `lexer` is borrowed for `'a`

Related

use an object inside a closure which is passed to a method of that object

i have a struct Screen with its implementation
pub struct Screen {
stdin: Stdin,
// types are irrelevant
stdout: MouseStdout,
}
impl Screen {
// ...
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
&self,
mut handler: F,
) {
let stdin = stdin();
for e in stdin.events() {
let e = e.unwrap();
match e {
Event::Key(Key::Ctrl('c')) => break,
_ => {
handler(&e);
},
}
}
}
}
and usage (which is wrong and know it)
let mut screen = Screen::new();
screen.init_screen();
screen.handle_keys_loop(|event| {
match event {
Event::Key(Key::Char('a')) => {
screen.println("hello there",15, 1, true);
},
_ => {}
}
});
screen.end_screen();
the error is
error[E0502]: cannot borrow `screen` as mutable because it is also borrowed as immutable
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ mutable borrow occurs here
| | |
| _____| immutable borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | println!("{} {} {} {}", "do something with a", 15, 1, true);
78 | | // tried to borrow as mutable
79 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
82 | | }
83 | | });
| |______- immutable borrow occurs here
and if i make self mut inside handle_keys_loop to get rid of cannot borrow screen as mutable because it is also borrowed as immutable
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
+ &mut self,
- &self
....
i get this error
error[E0499]: cannot borrow `screen` as mutable more than once at a time
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ second mutable borrow occurs here
| | |
| _____| first borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
80 | | }
81 | | });
| |______- first mutable borrow occurs here
what im trying to do: use the method handle_keys_loop of screen and pass screen inside the closure, which is passed to handle_keys_loop. basically, to use screen inside of screen.
how do i achieve that ?
some people told me to use RefCell, but that didnt work out very well, i got BorrowError.
i will use any workaround to just use screen inside the closure which is passed to screen's method.
thanks in advance.
One pattern I use to handle such a situation is to pass self: &mut Self back into the closure from handle and use that inside the closure. A simplified version of your code:
struct Screen {}
struct Event {}
impl Screen {
fn handle<F: FnMut(&mut Screen, Event)>(&mut self, mut handler: F) {
handler(self, Event {})
}
fn print(&mut self) {}
}
fn main() {
let mut screen = Screen {};
screen.handle(|screen, _event| screen.print());
screen.handle(|screen, _event| screen.print());
}
You can't do what you're trying to do because it violates Rust's rule that you can't mutate a value while something else has access to it.
However, your handle_keys_loop method doesn't even use self which means the &self parameter is redundant. There's no reason to give a function an argument it's not going to use (except when implementing a trait that requires it).
Just remove the argument:
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
mut handler: F,
) {
And call it as Screen::handle_keys_loop(|event| { ... }).
Alternatively, make it a free function, external to Screen entirely, since it doesn't depend on Screen in any way.

How do I mutate an enum and then return a reference to an enum variant?

I have an enum that can hold either an encoded type (i32) or a decoded type (String).
My goal is to write a function that converts the enum to the decoded state, and return a reference, but I can't do it: if I change the content of the enum first, I cannot return a reference.
enum Foo {
A(i32),
B(String),
}
use Foo::*;
impl Foo {
fn get_string(&mut self) -> &str {
match self {
A(i) => {
let s = i.to_string();
*self = B(s);
&s
}
B(string) => string,
}
}
}
I get
error[E0515]: cannot return value referencing local variable `s`
--> src/lib.rs:10:9
|
10 | / match self {
11 | | A(i) => {
12 | | let s = i.to_string();
13 | | *self = B(s);
14 | | &s
| | -- `s` is borrowed here
15 | | }
16 | | B(string) => string,
17 | | }
| |_________^ returns a value referencing data owned by the current function
error[E0382]: borrow of moved value: `s`
--> src/lib.rs:14:17
|
12 | let s = i.to_string();
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
13 | *self = B(s);
| - value moved here
14 | &s
| ^^ value borrowed here after move
Is what I want to do possible? If so, how can I do it?
The reference you return needs to point to the data inside Foo::B, not to your local variable s. It's easiest to do this in two steps – first do the conversion if necessary, then return the reference. After the first step it's guaranteed that *self is Foo::B, so we can mark the A branch in the match as unreachable!().
impl Foo {
fn get_string(&mut self) -> &str {
if let A(i) = *self {
*self = B(i.to_string());
}
match *self {
A(_) => unreachable!(),
B(ref s) => s,
}
}
}
(Note that I changed pattern matching to not use "match ergonomics", since this tends to be less confusing.)

How do we return a reference to a HashMap value from a method in a struct that owns the HashMap? [duplicate]

This question already has answers here:
HashMap borrow issue when trying to implement find or insert
(2 answers)
How to lookup from and insert into a HashMap efficiently?
(2 answers)
Closed 4 years ago.
Consider the following attempt to make a function memoizer (playground link):
use std::collections::HashMap;
pub struct Cacher<F, IN, OUT> {
function: F,
cache: HashMap<IN, OUT>,
}
impl<F, IN, OUT> Cacher<F, IN, OUT>
where
F: Fn(IN) -> OUT,
IN: std::cmp::Eq + std::hash::Hash + std::marker::Copy,
OUT: std::marker::Copy,
{
fn new(function: F) -> Cacher<F, IN, OUT> {
Cacher {
function: function,
cache: HashMap::new(),
}
}
fn at(&mut self, arg: IN) -> &OUT {
match self.cache.get(&arg) {
None => {
let val = (self.function)(arg);
self.cache.insert(arg, val);
&val // FAIL!
}
Some(val) => val,
}
}
}
The at method fails to compile:
error[E0597]: `val` does not live long enough
--> src/lib.rs:26:18
|
26 | &val // FAIL!
| ^^^ borrowed value does not live long enough
27 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 21:5...
--> src/lib.rs:21:5
|
21 | / fn at(&mut self, arg: IN) -> &OUT {
22 | | match self.cache.get(&arg) {
23 | | None => {
24 | | let val = (self.function)(arg);
... |
29 | | }
30 | | }
| |_____^
error[E0502]: cannot borrow `self.cache` as mutable because it is also borrowed as immutable
--> src/lib.rs:25:17
|
22 | match self.cache.get(&arg) {
| ---------- immutable borrow occurs here
...
25 | self.cache.insert(arg, val);
| ^^^^^^^^^^ mutable borrow occurs here
...
30 | }
| - immutable borrow ends here
My understanding is that in the case that the value must be computed, the returned &val isn't known to live long enough.
I tried a few things to explain to the compiler that the returned &val should be expected to live as long as the Cacher that contains it, but so far I have not succeeded.
How do we give the compiler the required information about &val's lifetime?

How to reduce lifetime conflicts?

I'm fear about lifetime question. I searched and got so many relative results. I feel so different between of them, and I think it is difficult to get the spirit from them. so I decide to ask.
The error occurred when invoking dao's method inside a Hyper service's call, and I can't fix it!
extern crate futures;
extern crate hyper;
use futures::future::Future;
use futures::Stream;
use hyper::server::{Http, Request, Response, Service};
use hyper::StatusCode;
use std::net::SocketAddr;
trait Dao {
fn input_data(&self, data: &str) -> bool;
}
struct MysqlDao;
impl Dao for MysqlDao {
fn input_data(&self, data: &str) -> bool {
unimplemented!()
}
}
struct HelloWorld<'a> {
dao: &'a Dao,
}
impl<'a> Service for HelloWorld<'a> {
type Request = Request;
type Response = Response;
type Error = hyper::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn call(&self, req: Request) -> Self::Future {
Box::new(req.body().concat2().map(|b| {
let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
let rtn = true; // line 35 this is ok
match rtn {
true => {
return Response::new()
.with_status(StatusCode::Ok)
.with_body(String::from("ok"));
}
false => {
return Response::new()
.with_status(StatusCode::UnprocessableEntity)
.with_body(String::from("error"));
}
}
}))
}
}
fn main() {
let addr = "127.0.0.1:3000".parse().unwrap();
static DAO: MysqlDao = MysqlDao;
web_startup(&addr, &DAO);
}
fn web_startup<T: Dao>(addr: &SocketAddr, dao: &'static T) {
let server = Http::new()
.bind(addr, move || Ok(HelloWorld { dao }))
.unwrap();
server.run().unwrap();
}
playground
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:33:9
|
33 | / Box::new(req.body().concat2().map(|b| {
34 | | let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
35 | | let rtn = true; // line 35 this is ok
36 | | match rtn {
... |
47 | | }
48 | | }))
| |___________^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 26:1...
--> src/main.rs:26:1
|
26 | / impl<'a> Service for HelloWorld<'a> {
27 | | type Request = Request;
28 | | type Response = Response;
29 | | type Error = hyper::Error;
... |
49 | | }
50 | | }
| |_^
note: ...so that the type `futures::Map<futures::stream::Concat2<hyper::Body>, [closure#src/main.rs:33:43: 48:10 self:&&HelloWorld<'a>]>` will meet its required lifetime bounds
--> src/main.rs:33:9
|
33 | / Box::new(req.body().concat2().map(|b| {
34 | | let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
35 | | let rtn = true; // line 35 this is ok
36 | | match rtn {
... |
47 | | }
48 | | }))
| |___________^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that expression is assignable (expected std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>, found std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response>>)
--> src/main.rs:33:9
|
33 | / Box::new(req.body().concat2().map(|b| {
34 | | let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
35 | | let rtn = true; // line 35 this is ok
36 | | match rtn {
... |
47 | | }
48 | | }))
| |___________^
The problem line is 34. When I replace line 34 with line 35, it works.
There's a couple of things going on with lifetimes in this code, and the error message is not that great.
The first thing is that your call function returns a trait object; that is, Box<T> where T is a trait instead of a concrete type. The default lifetime for a trait object is 'static, so Box<Future> is equivalent to Box<Future + 'static>. That explains where this line of the message comes from:
note: ...so that expression is assignable (expected std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>, found std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response>>)
In this case, you don't need your returned Future to have the 'static lifetime. Instead, you want it to have the same lifetime as self.dao, so change your type alias as follows:
type Future = Box<'a + Future<Item = Self::Response, Error = Self::Error>>;
The second thing is what variables your closure captures. Your closure refers to self, so it needs to save away that reference. This means the closure can't live past the end of the method - but you've already specified it will live as long as 'a; that is, it will live at least as long as self.dao.
Note that self in this method does not have the lifetime 'a. The instance of HelloWorld might have a shorter lifetime than the dao it has a reference to.
To fix this half of the problem, you need to allow the closure to capture only self.dao without capturing self. So you have to add
let dao = self.dao;
before the closure, and then refer to dao instead of self.dao inside the closure, so that it won't capture self. You also need to make the closure a move closure, otherwise it ends up capturing a reference to the reference, which still ties the lifetime to the scope of the function.
User red75prime, who originally posted this suggestion in a comment, made a playground with these changes. Lines 30, 33, and 34 are the important ones.
I found a way, but I think it's ugly.
Remove dao property from HelloWorld; add Sync to trait Dao; move out DAO to upper scope; invoke DAO directly from fn call.
Code : playground

Cannot borrow variable as mutable more than once at a time [duplicate]

This question already has answers here:
How to update-or-insert on a Vec?
(2 answers)
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
(1 answer)
Closed 5 years ago.
I'm trying to implement a trie but the borrow checker is really giving me a hard time:
struct Node {
// a trie node
value: char,
children: Vec<Node>,
}
impl Node {
fn add_child(&mut self, value: char) -> &mut Node {
// adds a child to given node
let vec: Vec<Node> = Vec::new();
let node = Node {
value,
children: vec,
};
self.children.push(node);
self.children.last_mut().unwrap()
}
fn get_child(&mut self, value: char) -> Option<&mut Node> {
// checks if given node has a child with given value, returns the child if it exists
for child in self.children.iter_mut() {
if child.value == value {
return Some(child);
}
}
None
}
fn has_child(&self, value: char) -> bool {
for child in self.children.iter() {
if child.value == value {
return true;
}
}
false
}
fn add_word(&mut self, word: String) {
let mut cursor = self;
for c in word.chars() {
match cursor.get_child(c) {
Some(node) => cursor = node,
None => cursor = cursor.add_child(c),
}
}
cursor.add_child('~');
}
}
The add_word method gives these 5 errors:
error[E0499]: cannot borrow `*cursor` as mutable more than once at a time
--> src/main.rs:41:19
|
41 | match cursor.get_child(c) {
| ^^^^^^ mutable borrow starts here in previous iteration of loop
...
47 | }
| - mutable borrow ends here
error[E0506]: cannot assign to `cursor` because it is borrowed
--> src/main.rs:42:31
|
41 | match cursor.get_child(c) {
| ------ borrow of `cursor` occurs here
42 | Some(node) => cursor = node,
| ^^^^^^^^^^^^^ assignment to borrowed `cursor` occurs here
error[E0506]: cannot assign to `cursor` because it is borrowed
--> src/main.rs:43:25
|
41 | match cursor.get_child(c) {
| ------ borrow of `cursor` occurs here
42 | Some(node) => cursor = node,
43 | None => cursor = cursor.add_child(c),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `cursor` occurs here
error[E0499]: cannot borrow `*cursor` as mutable more than once at a time
--> src/main.rs:43:34
|
41 | match cursor.get_child(c) {
| ------ first mutable borrow occurs here
42 | Some(node) => cursor = node,
43 | None => cursor = cursor.add_child(c),
| ^^^^^^ second mutable borrow occurs here
...
47 | }
| - first borrow ends here
error[E0499]: cannot borrow `*cursor` as mutable more than once at a time
--> src/main.rs:46:9
|
41 | match cursor.get_child(c) {
| ------ first mutable borrow occurs here
...
46 | cursor.add_child('~');
| ^^^^^^ second mutable borrow occurs here
47 | }
| - first borrow ends here
This is the Go code that I was trying to translate:
func (n *trieNode) AddWord(word string) {
cursor := n
for i := 0; i < len(word); i++ {
if cursor.HasChild(byte(word[i])) == nil {
cursor = cursor.AddChild(byte(word[i]))
} else {
cursor = cursor.HasChild(byte(word[i]))
}
}
// tilde indicates the end of the word
cursor.AddChild(byte('~'))
}

Resources