Search code examples
rustclosures

How to store a closure inside Rust struct?


struct User {
    id: i8,
    name: &'static str
}

struct UserMethods {
    add_user: Fn(User) -> (),
}

fn main() {
    UserMethods {
        add_user: |user| {

        }
    };
}

The compiler says,

error[E0277]: the size for values of type `(dyn Fn(User) + 'static)` cannot be known at compilation time
  --> src/main.rs:11:5
   |
11 | /     UserMethods {
12 | |         add_user: |user| {},
13 | |     };
   | |_____^ doesn't have a size known at compile-time

Solution

  • Fn is a trait, thus it is unsized. In order to store it in a struct or variable, you must use something that implements Sized otherwise the compiler cannot know how much memory to allocate.

    There are two ways to fix the issue:

    1. Use generics:
    struct UserMethods<T: Fn(User)> {
        add_user: T,
    }
    
    fn main() {
        UserMethods {
            add_user: |user| {},
        };
    }
    
    1. Use Box or any other smart pointer:
    struct UserMethods {
        add_user: Box<dyn Fn(User)>,
    }
    
    fn main() {
        UserMethods {
            add_user: Box::new(|user| {}),
        };
    }
    

    You can also use an ordinary function pointer (thanks @user2722968), but it's not as flexible as a closure (cannot capture anything from the environment):

    struct UserMethods {
        add_user: fn(User),
    }
    
    fn main() {
        UserMethods {
            add_user: |user| {},
        };
    }