Rust : Solving `()` doesn't implement `std::fmt::Display` error in Closure

Rust - Closure compiler error - unit type display trait not implemented

Recently, I have started to learn Rust programming language and while making a simple example that uses a closure, I came across a compile error that was not very informative. It was telling me that `()` doesn't implement `std::fmt::Display`. This post will show the code causing the error, what the error means, and the solution to the error.

The example code was very simple:

fn main() {
    let add = |a, b| {
        a+b;
    };

    let result=add(10, 20);
    println!("Result {}",result);
}

When trying to compile the above code, I got a compile error with the following error message:

error[E0277]: `()` doesn't implement `std::fmt::Display`
--> main.rs:7:26
  |
7| println!("Result {}",result);
  | ^^^^^^ `()` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `()`
  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
  = note: required by `std::fmt::Display::fmt`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

It turns out the issue was the extra semicolon at line a+b; inside the closure:

let add = |a, b| {
    a+b;
};

By removing the semicolon ;, the code worked as it should:

let add = |a, b| {
    a+b
};

Explanation of the compiler error

In Rust, every function and closure returns a value. We can return the value explicitly using return statement or implicitly where the last expression in the the function or closure is used as a return. In above example, that last expression is the line a+b and that is used as a return value.

So why does the line a+b make it an expression that returns a value?

Rust expressions and statements

Rust is comprised of statements and expressions. Expressions do not include ; semicolons and they return a value, while statements are instructions that carry out some action, include semicolons ; and do not return a value. A good explanation about expressions and statements can be found in this article.

Why () in the compiler error?

If function or a closure returns nothing (as it is with the case of a+b; in the above code as the ; semicolon turns that line into a statement and statements don't return anything), then what is returned is the unit type ().

We could think of () as a tuple with 0 elements. The unit type () is similar to void in other languages like C#. In Rust, the functions that don't return a value return () type.

Why std::fmt::Display in the compiler error?

Since the closure returns the unit type (), this is the value that the result variable receives.

let result=add(10, 20);

In the next line, the code tries to display the value of result:

println!("Result {}",result);

The println! macro is used to display a formatted output. Depending on the format used inside {}, different formatting trait is needed to be implemented by an argument. If no format is specified (as with above code using {}), then the argument needs to implement the Display trait.

If we look at std::fmt::Display trait, we can see that primitive types and various structs implement the Display trait, but the unit type () is not among them.

Let's again look at the error message:

`()` doesn't implement `std::fmt::Display`

So, the compiler error makes much more sense now. Closure returns unit type () and this is what println! tries to display, but the unit type () does not have std::fmt::Display trait implemented.

Conclusion

It can be challenging when you start a new programming language and even more so when the compiler gives you cryptic error messages. This was the case with me when I tried to compile a very simple closure example and received a `()` doesn't implement `std::fmt::Display` error message. In the end, the source of the error was the closure returning the unit type () and the println! macro trying to display the () as a formatted string.

Write a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.