typically
typically

Reputation: 3520

Using struct in place of function for FnOnce

This program compiles and runs successfully.

#[derive(Debug)]
struct MyError(i32);

fn main() {
    let m: Result<(), MyError> = Err(3).map_err(MyError);
    println!("{:?}", m); // output: Err(MyError(3))
}

The signature of map_err is

pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F>

which expects a FnOnce, for which I believe the type should be a function/closure. What is the reason the struct can be used successfully here?

Upvotes: 1

Views: 266

Answers (1)

Masklinn
Masklinn

Reputation: 42247

Because when you define a tuple struct, it defines the corresponding type as well as a constructor, which is a function, because why not. You can actually check this using the compiler, the tuple struct constructor isn't even any sort of weird function-like item, it's a function pointer like any function you'd define using fn (or a non-closure anonymous function).

Both have the same name but live in different namespaces, one being the "types namespace" and the other the "function namespace".

A clearer version of this is enum tuple constructors as there is no confusion between the type and its constructor: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d76337f3301927cfca67200b64dfa89c but it's rather the same principle.

Upvotes: 3

Related Questions