1

I have this generic type:

pub struct MyContainer<T, S> {
    array: Vec<T>,
    get_size: S,
    size: u32,
}

impl<T: Default, S> MyContainer<T, S>
where
    S: Fn(&T) -> u32,
{
    pub fn new(size: u32, get_size: S) -> MyContainer<T, S> {
        let array = Vec::with_capacity(size as usize);
        MyContainer {
            array,
            get_size,
            size,
        }
    }
}

I can easily create a container using compiler deduction magic:

pub fn get_size_func(h: &House) -> u32 {
    h.num_rooms
}
let container = MyContainer::new(6, get_size);

However, I'm hitting an issue when I try to instantiate my generic type in another struct:

pub struct City {
    suburbs: MyContainer<House, fn(&House) -> u32>,
}

impl City {
    pub fn new(num_houses: u32) -> City {
        let container = MyContainer::new(num_houses, get_size_func);
        City { suburbs: container }
    }
}

I get

error[E0308]: mismatched types
  --> src/lib.rs:44:25
   |
44 |         City { suburbs: container }
   |                         ^^^^^^^^^ expected fn pointer, found fn item
   |
   = note: expected type `MyContainer<_, for<'r> fn(&'r House) -> u32>`
              found type `MyContainer<_, for<'r> fn(&'r House) -> u32 {get_size_func}>`

Here's the Rust playground that reproduces the problem

2
  • Your question may be answered by the answers of Right way to have Function pointers in struct / How do I call a function through a member variable?. If you agree, we can mark this question as already answered. Commented Nov 2, 2018 at 2:26
  • Ah, I need fn instead of Fn. But I'm now hitting a case where when I try to call the City new function. Thanks for the other tips BTW, I'll try to create a new Rust playground should I have another question. Commented Nov 2, 2018 at 3:32

1 Answer 1

1

There's two answers to this question:

  1. Specifying the type parameters when creating the the container. I don't know why that works, but it does:

    let container = MyContainer::<House, fn(&House) -> u32>::new(num_houses, get_size_func);
    
  2. You can also define a generic function that calls a generic trait for an added kick. For example:

     let container = MyContainer::<House, fn(&House) -> u32>::new(num_houses, get_size_func2::<House>);
    

    get_size_func2 would be a trait bound generic function.

Here's the full playground. For both solutions, type parameters are required and not deduced in the City::new function.

Sign up to request clarification or add additional context in comments.

5 Comments

What is a function signature and type? — every function has a unique type that is not the function pointer type.
@Shepmaster can you hint as to why this is? It seems that to have generic functions (e.g. a table of binary operators that take two u64s and return another u64) requires function signatures to be repeated with an as fn(x) -> y cast. What's the benefit?
@Shepmaster just wondering if you knew the reason that the "every function has a unique type" feature was added to Rust. Like, what problem that solves. I just discovered it while trying to apply a series of functions to some input, and was surprised that it was not possible without casting them to a more generic function pointer with as.
@Shepmaster oh just noticed your example in the Playground where that isn't necessary. Now I'm more confused than ever! :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.