Memory question?

Hello, I'm testing a readable way to schedule my runtime in rust (on the "nightly" release)
and I have simple question if I do the following code the component "f" of my struct "Functionholder" is a pointer? OR a copy on the heap of the same function ? of course you guess my issue if have a vector of this struct of 20 elements by instance that will be 20 copy of the same code or just 20 pointers on the same static memory ? at least I just want a simple function (pointer or ref in rust) in a vector list. thanks :slight_smile:
following the playground:

#![feature(fn_traits)]
struct Functionholder{
    f:Box<dyn Fn(u32)->u32>,
}
impl Functionholder{
    fn new(x:Box<dyn Fn(u32)->u32>)->Self{
        Self{
            f:x,
        }
    }
}
fn exemple_function(a:u32)->u32{
    println!("{}",a);
    a
}
fn main(){
    let func = Functionholder::new(Box::new(exemple_function));
    func.f.call((10,));
}

(Playground)

Output:

10

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 1.43s
     Running `target/debug/playground`

Functions aren't copiable; an fn item is only accessible through a pointer to it. In your case, it's entirely unnecessary to stack yet another level of indirection and a heap allocation on top of this. Just store fn(u32) -> u32, a function pointer type, in your struct directly.

BTW you don't need any nightly #![feature] for this: Playground

Good Im checking that

Thanks so much :slight_smile:

just curious, what is it that causes the heap allocation? You explained the details well here but just for the sake of references and to make sure I'm not missing something:

From Box::new():

This doesn’t actually allocate if T is zero-sized.

From Functions reference (emphasis mine):

When referred to, a function yields a first-class value of the corresponding zero-sized function item type, which when called evaluates to a direct call to the function.

So wouldn't Box:new(exemple_function) not allocate (the Box is just storing a pointer on the stack)?

The box.

The box always heap-allocates its pointer if the pointed type is not zero-sized. If it is zero-sized, you get an invalid but not null pointer that points nowhere. It never points to the stack.

That could only work if you culd box the function item directly. You can't, because its type is not nameable, and you can't get to the function item directly, by-value. And the fn(u32) -> u32 type doesn't uniquely identify the function item anyway, so there has to be a function pointer and dynamic dispatch somewhere. You get that function pointer by referring to the function item and coercing it to type fn(u32) -> u32. Therefore, Box<fn(u32) -> u32> is a boxed, non-zero-sized pointer, stored on the heap.

3 Likes

apparently you can not ".call()" the function without the feature fn_traits enabled...

Indeed, but you don't need to. You can just call it directly using the () operator.

2 Likes