Can anything have the Fn and the PartialEq trait

Hopefully a really quick question is it possible to pass anything into the function bellow. I have a feeling there isn't as closures all have there own unique type (and so couldn't have PartialEq, at least not in any useful way ) and I think the only thing that would satisfy Fn(16) -> A would be a closure that took a u16.

pub fn example<T,A>(executable: T) -> String 
where
    A: 'static + PartialEq + IntoIterator<Item = String>,
    T: 'static + PartialEq + Fn(u16) -> A
{
 /// Some code that does something and returns a String
}

Thanks in advance,

Rich

Yes, function pointers implement PartialEq.

4 Likes

Even if function pointers weren't already an example, you can implement traits for trait objects (or alternatively also for boxed trait objects if things needed to be Sized); when the trait has an Fn-bound as supertrait, this will allow you to fulfill the desired combination of trait bounds, e.g.:

trait Foo<A>: Fn(u16) -> A {}
impl<T: ?Sized, A> Foo<A> for T where T: Fn(u16) -> A {}

impl<A> PartialEq for dyn Foo<A> + '_ {
    fn eq(&self, other: &Self) -> bool {
        true
    }
}

fn example<T, A>(executable: T) -> String
where
    A: 'static + PartialEq + IntoIterator<Item = String>,
    T: 'static + PartialEq + Fn(u16) -> A,
{
    todo!()
}

fn demo<T, A>(executable: T) -> String
where
    A: 'static + PartialEq + IntoIterator<Item = String>,
    T: 'static + Fn(u16) -> A,
{
    example(Box::new(executable) as Box<dyn Foo<_>>)
}

Still you are right in questioning whether that function is particularly useful and easy to call in practice with some useful arguments. IMO, it indeed won’t be all that useful after all, at least until Fn-traits become implementable on custom types. Except if the intended use-case involves function-pointers, but then directly requiring a function pointer type would appear more logical to me.

3 Likes

I tried calling it with a simple example bellow but I'm still getting an error saying PatialEq is still not implemented even though like you said it is implemented for function pointers.


fn tester (value: u16) -> [String;1] {
    let page = String::from("w");
    let pages = [page];
    pages
}

fn example() -> () {
    strange_function(tester);    
}

fn strange_function<T,A>(props: T) -> String 
where
    A: 'static + PartialEq + IntoIterator<Item = String>,
    T: 'static + PartialEq + Fn(u16) -> A
{
    unimplemented!()
}

using this as a simple example I'm still getting the error

Can't compare `fn(u16) -> [std::string::String; 1] {pages::about::tester}` with `fn(u16) -> [std::string::String; 1] {pages::about::tester}`
the trait `std::cmp::PartialEq` is not implemented for `fn(u16) -> [std::string::String; 1] {pages::about::tester}`

Have I got the syntax wrong or am I still missing something ?

The type you are passing to sub_nav is a function item and not a function pointer. Function items are zero-sized types that encodes the specific function directly in their type, whereas function pointers are pointer-sized types that can store a pointer to any function of the appropriate arguments. Read the creating function pointers heading on the page I linked earlier for more.

You can fix it like this. This will use the built-in coercion from function item to function pointer.

fn example() {
    let my_fn_ptr: fn(u16) -> [String;1] = tester;
    sub_nav(my_fn_ptr);
}

Thank you so much for your help