Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I solve the error "the precise format of `Fn`-family traits' type parameters is subject to change"?

Tags:

rust

traits

I have written a problem solver in Rust which as a subroutine needs to make calls to a function which is given as a black box (essentially I would like to give an argument of type Fn(f64) -> f64).

Essentially I have a function defined as fn solve<F>(f: F) where F : Fn(f64) -> f64 { ... } which means that I can call solve like this: solve(|x| x);

What I would like to do is to pass a more complex function to the solver, i.e. a function which depends on multiple parameters etc.

I would like to be able to pass a struct with a suitable trait implementation to the solver. I tried the following:

struct Test;
impl Fn<(f64,)> for Test {}

This yield the following error:

error: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)

I would also like to add a trait which includes the Fn trait (which I don't know how to define, unfortunately). Is that possible as well?

Edit: Just to clarify: I have been developing in C++ for quite a while, the C++ solution would be to overload the operator()(args). In that case I could use a struct or class like a function. I would like to be able to

  1. Pass both functions and structs to the solver as arguments.
  2. Have an easy way to call the functions. Calling obj.method(args) is more complicated than obj(args) (in C++). But it seems that this behavior is not achievable currently.
like image 752
hfhc2 Avatar asked Dec 26 '16 13:12

hfhc2


1 Answers

The direct answer is to do exactly as the error message says:

Use parenthetical notation instead

That is, instead of Fn<(A, B)>, use Fn(A, B)

The real problem is that you are not allowed to implement the Fn* family of traits yourself in stable Rust.

The real question you are asking is harder to be sure of because you haven't provided a MCVE, so we are reduced to guessing. I'd say you should flip it around the other way; create a new trait, implement it for closures and your type:

trait Solve {
    type Output;
    fn solve(&mut self) -> Self::Output;
}

impl<F, T> Solve for F
where
    F: FnMut() -> T,
{
    type Output = T;

    fn solve(&mut self) -> Self::Output {
        (self)()
    }
}

struct Test;
impl Solve for Test {
    // interesting things
}

fn main() {}
like image 191
Shepmaster Avatar answered Nov 14 '22 08:11

Shepmaster