How do I create a HashMap with value of function? - rust

I'm trying to set HashMap of functions in a struct to a field in the struct and call them like below code. But it has compiler error. How can I fix?
main.rs
use std::collections::HashMap;
struct A{
pub funcs: HashMap<&'static str, fn()->()>,
f1:i32,
f2:i32
}
impl A {
fn func1(&mut self) {self.f1+=1;println!("func1 has called {} time(s)",self.f1);}
fn func2(&mut self) {self.f2+=1;println!("func2 has called {} time(s)",self.f2);}
fn set_funcs(&mut self) {
self.funcs = HashMap::from([("f1",Self::func1),("f2",Self::func2)]);
}
}
fn main() {
let mut a = A{funcs:HashMap::new(),f1:0,f2:0};
a.set_funcs();
a.funcs.get("f1").unwrap()();
}
compiler error
error[E0308]: mismatched types
--> src/main.rs:12:58
|
12 | self.funcs = HashMap::from([("f1",Self::func1),("f2",Self::func2)]);
| ^^^^^^^^^^^ expected fn item, found a different fn item
|
= note: expected fn item `for<'r> fn(&'r mut A) {A::func1}`
found fn item `for<'r> fn(&'r mut A) {A::func2}`
error[E0308]: mismatched types
--> src/main.rs:12:18
|
12 | self.funcs = HashMap::from([("f1",Self::func1),("f2",Self::func2)]);
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
| |
| expected due to the type of this binding
|
= note: expected struct `HashMap<&'static str, fn()>`
found struct `HashMap<&str, for<'r> fn(&'r mut A) {A::func1}>`

Your functions have an argument: &mut self. self has type Self/A. A::func1 is fn(&mut A) -> () not fn() -> ()
use std::collections::HashMap;
struct A{
pub funcs: HashMap<&'static str, fn(&mut Self)->()>,
f1:i32,
f2:i32
}
impl A {
fn func1(&mut self) {self.f1+=1;println!("func1 has called {} time(s)",self.f1);}
fn func2(&mut self) {self.f2+=1;println!("func2 has called {} time(s)",self.f2);}
fn set_funcs(&mut self) {
self.funcs.insert("f1", Self::func1);
self.funcs.insert("f2", Self::func2);
}
}
fn main() {
let mut a = A{funcs:HashMap::new(),f1:0,f2:0};
a.set_funcs();
a.funcs.get("f1").unwrap()(&mut a);
}

Related

Rust passing closures and they lifetime

Hi I try to pass my closure to mockall crate returning function in following way:
pub fn set_dialog_game_selection(dialogs: &mut Box<MockAsk>, steam_id: String) {
dialogs
.expect_ask_for_game_decision_if_needed_and_set_game_to_launch()
.returning(ask_for_game_decision_if_needed_return_mock(steam_id));
}
pub fn ask_for_game_decision_if_needed_return_mock<'x, 'y>(
steam_id: String,
) -> Box<dyn Fn(&'x mut REvilConfig, &'y mut REvilManagerState) -> ResultDialogsErr<()> + Send> {
let default = move |_: &'x mut REvilConfig, state: &'y mut REvilManagerState| {
state.selected_game_to_launch = Some(steam_id.clone());
Ok(())
};
return Box::new(default);
}
but I get
error[E0308]: mismatched types
--> src\tests\integration.rs:128:14
|
128 | .returning(ask_for_game_decision_if_needed_return_mock(steam_id.to_string()));
| ^^^^^^^^^ lifetime mismatch
|
= note: expected associated type `<dyn Fn(&mut configStruct::REvilConfig, &mut rManager_header::REvilManagerState) -> Result<(), error_stack::Report<DialogsErrors>> + Send as FnOnce<(&mut configStruct::REvilConfig, &mut rManager_header::REvilManagerState)>>::Output`
found associated type `<dyn Fn(&mut configStruct::REvilConfig, &mut rManager_header::REvilManagerState) -> Result<(), error_stack::Report<DialogsErrors>> + Send as FnOnce<(&mut configStruct::REvilConfig, &mut rManager_header::REvilManagerState)>>::Output`
note: the lifetime requirement is introduced here
--> src\dialogs\dialogs.rs:54:10
|
54 | ) -> ResultDialogsErr<()>;
| ^^^^^^^^^^^^^^^^^^^^
P.S I'm writting mod manager for Resident Evil game that's why "REvil" :p
P.S2 In the end I managed to rewrite it like:
pub fn set_dialog_game_selection(dialogs: &mut Box<MockAsk>, steam_id: String) {
dialogs
.expect_ask_for_game_decision_if_needed_and_set_game_to_launch()
.returning(move |_, state| {
set_game_decision(steam_id.clone(), state);
Ok(())
});
}
pub fn set_game_decision(steam_id: String, state: &mut REvilManagerState) {
state.selected_game_to_launch = Some(steam_id);
}
But why my first approach doeasn't work? :(
Function signature I'm trying to mock is as follow:
pub type ResultDialogsErr<T> = Result<T, DialogsErrors>;
fn ask_for_game_decision_if_needed_and_set_game_to_launch(
&mut self,
config: &mut REvilConfig,
state: &mut REvilManagerState,
) -> ResultDialogsErr<()>;
If you remove the manual lifetime annotations, it works:
pub fn ask_for_game_decision_if_needed_return_mock(
steam_id: String,
) -> Box<dyn Fn(&mut REvilConfig, &mut REvilManagerState) -> DynResult<()> + Send> {
let default = move |_: &mut REvilConfig, state: &mut REvilManagerState| {
state.selected_game_to_launch = Some(steam_id.clone());
Ok(())
};
return Box::new(default);
}

How do I fix the lifetime mismatch when returning a mutable reference to the struct's field from a trait method?

This is my attempt to return a mutable reference to the struct's field.
pub trait Objective {
fn get_children<'a>(&'a mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>>;
fn get_parent(&'_ mut self) -> &'_ mut Box<dyn Objective>;
fn update(&'_ self) -> ();
}
// #[derive(Objective)]
pub struct Object<'a> {
children: Vec<&'a mut Box<dyn Objective>>,
parent: &'a mut Box<dyn Objective>,
}
impl<'a> Objective for Object<'a> {
fn get_children(&'a mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>> {
return &mut self.children;
}
fn get_parent(&'_ mut self) -> &'_ mut Box<dyn Objective> {
return self.parent;
}
fn update(&'_ self) -> () {}
}
There is a problem with the lifetime. Here is the error given by the compiler:
error[E0308]: method not compatible with trait
--> src/lib.rs:14:5
|
14 | fn get_children(&'a mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&'a mut Object<'a>) -> &'a mut std::vec::Vec<&'a mut std::boxed::Box<(dyn Objective + 'static)>>`
found fn pointer `fn(&'a mut Object<'a>) -> &'a mut std::vec::Vec<&'a mut std::boxed::Box<(dyn Objective + 'static)>>`
note: the lifetime `'a` as defined on the method body at 14:5...
--> src/lib.rs:14:5
|
14 | fn get_children(&'a mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 13:6
--> src/lib.rs:13:6
|
13 | impl<'a> Objective for Object<'a> {
| ^^
error[E0308]: method not compatible with trait
--> src/lib.rs:14:5
|
14 | fn get_children(&'a mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&'a mut Object<'a>) -> &'a mut std::vec::Vec<&'a mut std::boxed::Box<(dyn Objective + 'static)>>`
found fn pointer `fn(&'a mut Object<'a>) -> &'a mut std::vec::Vec<&'a mut std::boxed::Box<(dyn Objective + 'static)>>`
note: the lifetime `'a` as defined on the impl at 13:6...
--> src/lib.rs:13:6
|
13 | impl<'a> Objective for Object<'a> {
| ^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the method body at 14:5
--> src/lib.rs:14:5
|
14 | fn get_children(&'a mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here is my earlier attempt at this which where I did not explicitly specify the lifetime:
pub trait Objective {
fn get_children(&'_ mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>>;
fn get_parent(&'_ mut self) -> &'_ mut Box<dyn Objective>;
fn update(&'_ self) -> ();
}
// #[derive(Objective)]
pub struct Object<'a> {
children: Vec<&'a mut Box<dyn Objective>>,
parent: &'a mut Box<dyn Objective>,
}
impl Objective for Object<'_> {
fn get_children(&'_ mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>> {
return &mut self.children;
}
fn get_parent(&'_ mut self) -> &'_ mut Box<dyn Objective> {
return self.parent;
}
fn update(&'_ self) -> () {}
}
And I've gotten a similar error:
error[E0308]: mismatched types
--> src/lib.rs:15:16
|
15 | return &mut self.children;
| ^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected mutable reference `&mut std::vec::Vec<&mut std::boxed::Box<(dyn Objective + 'static)>>`
found mutable reference `&mut std::vec::Vec<&mut std::boxed::Box<(dyn Objective + 'static)>>`
note: the anonymous lifetime #1 defined on the method body at 14:5...
--> src/lib.rs:14:5
|
14 | / fn get_children(&'_ mut self) -> &'_ mut Vec<&'_ mut Box<dyn Objective>> {
15 | | return &mut self.children;
16 | | }
| |_____^
note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 13:27
--> src/lib.rs:13:27
|
13 | impl Objective for Object<'_> {
| ^^
How do I fix this?
Specify the lifetime on the trait and it works:
pub trait Objective<'a> {
fn get_children(&mut self) -> &mut Vec<&'a mut Box<dyn Objective<'a>>>;
fn get_parent(&mut self) -> &mut Box<dyn Objective<'a>>;
fn update(&self) -> ();
}
// #[derive(Objective)]
pub struct Object<'a> {
children: Vec<&'a mut Box<dyn Objective<'a>>>,
parent: Box<dyn Objective<'a>>,
}
impl<'a> Objective<'a> for Object<'a> {
fn get_children(&mut self) -> &mut Vec<&'a mut Box<dyn Objective<'a>>> {
&mut self.children
}
fn get_parent(&'_ mut self) -> &mut Box<dyn Objective<'a>> {
&mut self.parent
}
fn update(&'_ self) -> () {}
}
By specifying the lifetime on Objective, we can make sure that implementers will return a Vec of mutable references that satisfies the same lifetime requirements as the one needed by the trait.

Rust function to return generic trait

I have two structs implementing same trait. I need a single fuction that returs object of any of these structure.
trait
pub trait DbfFile{
fn new(fields: HashMap<String, FieldValue>) -> Self;
}
The structures are
pub struct InsertableAttachable {
pub f1: String,
pub f2: String,
pub f3: String,
pub f4: i8,
}
impl DbfFile for InsertableAttachable{
fn new(fields: HashMap<String, FieldValue, RandomState>) -> Self {
InsertableAttachable {
// fields
}
}
}
// Converting this to generic
impl InsertableAttachable{
pub fn get_data_vector(mut iter: DatabaseRecordIterator) -> Vec<InsertableAttachable>{
let mut db_data: Vec<InsertableAttachable> = vec!();
while let Some(table_row) = iter.next() {
let fields = table_row.fields;
db_data.push(InsertableAttachable::new(fields));
};
db_data
}
}
And another structure
pub struct InsertableAttached {
pub f1: String,
pub f2: i32,
pub f3: i32,
}
impl DbfFile for InsertableAttached {
fn new(fields: HashMap<String, FieldValue, RandomState>) -> Self {
InsertableAttached {
// fields
}
}
}
// Converting this to generic
impl InsertableAttached{
pub fn get_data_vector(mut iter: DatabaseRecordIterator) -> Vec<InsertableAttached>{
let mut db_data: Vec<InsertableAttached> = vec!();
while let Some(table_row) = iter.next() {
let fields = table_row.fields;
db_data.push(InsertableAttached::new(fields));
};
db_data
}
}
Here are example like this returns box / struct and this one returns an option.
The following function has compile time error
error[E0277]: the size for values of type `(dyn models::traits::DbfFile + 'static)` cannot be known at compilation time
--> src/dbf.rs:75:1
|
75 | / pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<DbfFile>{
76 | | let mut db_data: Vec<DbfFile> = vec!();
77 | | while let Some(table_row) = iter.next() {
78 | | let fields = table_row.fields;
... |
81 | | db_data
82 | | }
| |_^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn models::traits::DbfFile + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required by `std::vec::Vec`
error[E0038]: the trait `models::traits::DbfFile` cannot be made into an object
--> src/dbf.rs:75:1
|
75 | pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<DbfFile>{
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `models::traits::DbfFile` cannot be made into an object
You would need to box the results in order to be able to return a heterogenous collection via dynamic dispatch:
pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<Box<dynDbfFile>>
However you will then get the following error:
| pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<Box<dyn DbfFile>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DbfFile` cannot be made into an object
|
The reason for this is that your function returns Self - which is different for each implementation. You would need to change it to a common type to make the trait object-safe (allow dynamic dispatch).
An alternative could be to return multiple types via an enumeration:
enum GetDataVectorResult {
Attachable(InsertableAttachable),
Attached(InsertableAttached),
}
pub fn get_data_vector(&mut iter: DatabaseRecordIterator) -> Vec<GetDataVectorResult>

Rust: error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements

This is the minimal code:
struct Node<T> {
item: T,
next: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;
pub struct IterMut<'a, T>(&'a mut Link<T>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.0.as_mut().map(|boxed_node| {
self.0 = &mut boxed_node.next;
&mut boxed_node.item
})
}
}
As far as I understand, there should be no problem. I have done a lot of searching, but no way.
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:13:16
|
13 | self.0.as_mut().map(|boxed_node| {
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src/lib.rs:12:5
|
12 | / fn next(&mut self) -> Option<Self::Item> {
13 | | self.0.as_mut().map(|boxed_node| {
14 | | self.0 = &mut boxed_node.next;
15 | | &mut boxed_node.item
16 | | })
17 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:13:9
|
13 | self.0.as_mut().map(|boxed_node| {
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 10:6...
--> src/lib.rs:10:6
|
10 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:14:22
|
14 | self.0 = &mut boxed_node.next;
| ^^^^^^^^^^^^^^^^^^^^
We can rewrite your code as:
struct Node<T> {
item: T,
next: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;
pub struct IterMut<'a, T>(&'a mut Link<T>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(boxed_node) = self.0 {
self.0 = &mut boxed_node.next;
Some(&mut boxed_node.item)
}
else {
None
}
}
}
You can see that boxed_node life end at the end of the function so you can't return a reference link to it.
The solution is to take a reference of the box and not a reference to the option:
struct Node<T> {
item: T,
next: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;
pub struct IterMut<'a, T>(Option<&'a mut Box<Node<T>>>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(boxed_node) = self.0.take() {
self.0 = boxed_node.next.as_mut();
Some(&mut boxed_node.item)
}
else {
None
}
}
}
You can also remove the Box:
struct Node<T> {
item: T,
next: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;
pub struct IterMut<'a, T>(Option<&'a mut Node<T>>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(boxed_node) = self.0.take() {
self.0 = boxed_node.next.as_mut().map(AsMut::as_mut);
Some(&mut boxed_node.item)
}
else {
None
}
}
}

How can I set appropriate lifetime for lifetime parameter when implementing a std Trait [duplicate]

I want to implement FromStr for a struct with a lifetime parameter:
use std::str::FromStr;
struct Foo<'a> {
bar: &'a str,
}
impl<'a> FromStr for Foo<'a> {
type Err = ();
fn from_str(s: &str) -> Result<Foo<'a>, ()> {
Ok(Foo { bar: s })
}
}
pub fn main() {
let foo: Foo = "foobar".parse().unwrap();
}
However, the compiler complains:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:11:12
|
11 | Ok(Foo { bar: s })
| ^^^
|
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Foo<'a>, ()>
--> src/main.rs:9:5
|
9 | fn from_str(s: &str) -> Result<Foo<'a>, ()> {
| ^
Changing the impl to
impl<'a> FromStr for Foo<'a> {
type Err = ();
fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
Ok(Foo { bar: s })
}
}
gives this error
error[E0308]: method not compatible with trait
--> src/main.rs:9:5
|
9 | fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
| ^ lifetime mismatch
|
= note: expected type `fn(&str) -> std::result::Result<Foo<'a>, ()>`
= note: found type `fn(&'a str) -> std::result::Result<Foo<'a>, ()>`
note: the anonymous lifetime #1 defined on the block at 9:51...
--> src/main.rs:9:52
|
9 | fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
| ^
note: ...does not necessarily outlive the lifetime 'a as defined on the block at 9:51
--> src/main.rs:9:52
|
9 | fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
| ^
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Foo<'a>, ()>
--> src/main.rs:9:5
|
9 | fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
| ^
Playpen
I don't believe that you can implement FromStr in this case.
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err>;
There's nothing in the trait definition that ties the lifetime of the input to the lifetime of the output.
Not a direct answer, but I'd just suggest making a constructor that accepts the reference:
struct Foo<'a> {
bar: &'a str
}
impl<'a> Foo<'a> {
fn new(s: &str) -> Foo {
Foo { bar: s }
}
}
pub fn main() {
let foo = Foo::new("foobar");
}
This has the side benefit of there not being any failure modes - no need to unwrap.
You could also just implement From:
struct Foo<'a> {
bar: &'a str,
}
impl<'a> From<&'a str> for Foo<'a> {
fn from(s: &'a str) -> Foo<'a> {
Foo { bar: s }
}
}
pub fn main() {
let foo: Foo = "foobar".into();
}

Resources