Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clone a function pointer

Tags:

rust

I have a structure with a field which is a function pointer. I want to implement the Clone trait for that struct, but I can't because function pointers can't be cloned if they have at least one parameter:

fn my_fn(s: &str) {
    println!("in my_fn {}", s);
}

type TypeFn = fn(s: &str);

#[derive(Clone)]
struct MyStruct {
    field: TypeFn
}

fn main() {
    let my_var = MyStruct{field: my_fn};
    let _ = my_var.clone();
}

Link to playground.

like image 390
Moebius Avatar asked Oct 31 '15 17:10

Moebius


2 Answers

Function pointers with references in their types don't implement Clone because of issue #24000. This means that you can't #[derive(Clone)] for types containing them; you have to implement it manually.

But function pointers are Copy, so you can impl Copy for your type and then use that to manually impl Clone:

impl Copy for MyStruct {}

impl Clone for MyStruct {
    fn clone(&self) -> Self { *self }
}

Playpen link.

like image 142
mbrubeck Avatar answered Oct 17 '22 15:10

mbrubeck


The problem is not that function pointers in general are not clonable, but that you actually have a function that is generic over the lifetime of the &str. For example if you replace the &str with i32 your code will compile, because i32 has no lifetimes. In your situation you need to make the lifetimes on the function pointer explicit:

type TypeFn<'a> = fn(s: &'a str);

This obviously bubbles up to the struct, too:

#[derive(Clone)]
struct MyStruct<'a> {
    field: TypeFn<'a>
}

This prevents the following kind of code:

let my_var = MyStruct{field: my_fn};
let s = String::new();
(my_var.field)(&s);

Actually the problem is that it's a bug. As shown in @MattBrubeck 's answer Function pointers implement Copy. So you can just implement Clone manually by using the function pointer's Copy impl:

impl Clone for MyStruct {
    fn clone(&self) -> Self {
        MyStruct {
            field: self.field,
        }
    }
}
like image 39
oli_obk Avatar answered Oct 17 '22 17:10

oli_obk