#![feature(unboxed_closures)]
#![feature(fn_traits)]
struct foo;
impl std::ops::Add for foo {
type Output = foo;
fn add(self, x: foo) -> foo {
p
You cannot yet implement the Fn*
traits in stable Rust. This is only possible with the nightly compiler using #[feature]
!
It's very useful to fully read the trait that you are implementing to see how to implement it. The Fn trait is defined as:
pub trait Fn<Args>: FnMut<Args> {
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
Notice any differences between the implementation and the definition? I see many:
The implementation doesn't provide a value for Args
! That's what the compiler is pointing at. See also Wrong number of type arguments: expected 1 but found 0
The implementation doesn't implement the supertrait FnMut, which itself requires the supertrait FnOnce. FnOnce
is where the associated type Output
is declared.
The implementation neglects to define what concrete type Output
should be.
The implementation returns Self
while the trait returns Self::Output
.
The implementation doesn't accept the second argument to call
. This argument contains any arguments passed in.
Additionally, types in Rust use PascalCase
, not snake_case
, so it should be Foo
.
#![feature(unboxed_closures)]
#![feature(fn_traits)]
struct Foo;
impl Fn<()> for Foo {
extern "rust-call" fn call(&self, _args: ()) {
println!("Call (Fn) for Foo");
}
}
impl FnMut<()> for Foo {
extern "rust-call" fn call_mut(&mut self, _args: ()) {
println!("Call (FnMut) for Foo");
}
}
impl FnOnce<()> for Foo {
type Output = ();
extern "rust-call" fn call_once(self, _args: ()) {
println!("Call (FnOnce) for Foo");
}
}
fn main() {
let x = Foo;
x();
}
Normally though, only one trait's implementation would have interesting code in it and the other trait implementations would delegate to it:
extern "rust-call" fn call(&self, args: ()) {
println!("Foo called, took args: {:?}", args);
}
// ...
extern "rust-call" fn call_mut(&mut self, args: ()) {
self.call(args)
}
// ...
extern "rust-call" fn call_once(self, args: ()) {
self.call(args)
}
See also: