Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to create an alias of a specific FnMut?

I want to work with FnMut(&[f32]) -> f32, to not copy/paste full signature, I want to introduce some kind of alias, but

type Boo = FnMut(&[f32]) -> f32;

fn f<F: Boo>(mut f: F) {}

Causes a compiler error:

error[E0404]: expected trait, found type alias `Boo`
 --> src/main.rs:3:13
  |
3 |     fn f<F: Boo>(mut f: F) {}
  |             ^^^ type aliases cannot be used for traits

I then tried:

trait Boo: FnMut(&[f32]) -> f32 {}

fn f<F: Boo>(mut f: F) {}

it compiled, but if I try to use Boo in place of trait in another place:

trait Boo: FnMut(&[f32]) -> f32 {}

struct X(Vec<Box<Boo>>);

I get:

error[E0191]: the value of the associated type `Output` (from the trait `std::ops::FnOnce`) must be specified
 --> src/main.rs:3:18
  |
3 | struct X(Vec<Box<Boo>>);
  |                  ^^^ missing associated type `Output` value

Is there any way to create an alias of a specific FnMut which I can use instead of FnMut(&[f32]) -> f32?

like image 914
user1244932 Avatar asked May 29 '17 16:05

user1244932


1 Answers

Trait aliases are not currently part of the language. However, there is an accepted RFC for exactly that. It's hard to predict exactly when it will be implemented, but accepting the RFC represents a commitment to implement it at some point in the future.

The reason for your error is that your Boo trait is a subtype of FnMut and any implementation must also provide the required associated type Output. But the compiler still doesn't know which implementation will be provided, so you need to tell it what the type of Output will be:

struct X(Vec<Box<Boo<Output = f32>>>);

This is a little clunky, and I feel like it's an area for improvement. Intuitively, it seems that Output could be inferred from -> f32, but I could be wrong here.

Even with that error fixed, Boo is strictly a subtype of FnMut(&[f32]) so you can't just provide any closure where Boo is expected. That closure must also implement your trait. You can do this as a blanket implementation for all FnMut(&[f32]) -> f32, like this:

impl <F> Boo for F where F: FnMut(&[f32]) -> f32 {}

Now any Boo is an FnMut(&[f32]) -> f32 (by subtyping), and any FnMut(&[f32]) -> f32 is a Boo (by the blanket implementation).

like image 123
Peter Hall Avatar answered Oct 07 '22 22:10

Peter Hall