Expected feature core :: ops :: FnMut, type parameter found

I don't understand why the code below won't compile. It looks like rust just doesn't "expand" the type parameter, as it looks like it matches me.

Code (rusty playpen: http://is.gd/gC82I4 )

use std::sync::{Arc, Mutex};

struct Data{
    func: Option<Box<FnMut(String) + Send>>
}

fn newData<F>(func: Option<Box<F>>) -> Data
where F: FnMut(String) + Send{
    Data{
        func: func
    }
}

fn main(){
    let _ = newData(Some(Box::new(|msg|{})));
}

      

Mistake

<anon>:10:15: 10:19 error: mismatched types:
 expected `core::option::Option<Box<core::ops::FnMut(collections::string::String) + Send>>`,
    found `core::option::Option<Box<F>>`
(expected trait core::ops::FnMut,
    found type parameter) [E0308]
<anon>:10         func: func
                        ^~~~
error: aborting due to previous error
playpen: application terminated with error code 101

      

+3


source to share


2 answers


You need to help the rust by at least partially separating the cast from Box<F>

to Box<FnMut>

.

Since Box<Trait>

it implies Box<Trait + 'static>

, you also need to add the value F: 'static

.



struct Data {
    func: Option<Box<FnMut(String) + Send>>
}

fn new_data<F>(func: Option<Box<F>>) -> Data where
    F: FnMut(String) + Send + 'static
{
    Data {
        func: func.map(|x| x as Box<_>)
    }
}

fn main() {
    let _ = new_data(Some(Box::new(|msg|{ })));
}

      

It should be noted that Box<F>

both Box<FnMut ...>

are not the same type, but the former are in most cases automatically converted to the latter. Inside the option here, we just needed to help the conversion by writing an explicit cast.

+3


source


While user139873's answer is absolutely correct, I would like to add that it is more idiomatic to pass a closure to a function by value and insert it into a function:

struct Data {
    func: Option<Box<FnMut(String) + Send>>
}

fn new_data<F>(func: Option<F>) -> Data where
        F: FnMut(String) + Send + 'static {
    Data {
        func: func.map(|f| Box::new(f) as Box<_>)
    }
}

fn main() {
    let _ = new_data(Some(|msg| {}));
}

      



This way you place fewer restrictions on the caller and their code becomes simpler.

+3


source







All Articles