This is the Result<T, E>
. It is re-exported various places, such as in std
, but it is defined in core
so that no_std
libraries can also use it. (In general, things defined in core
are re-exported in std
.) T
is the Ok
payload type and E
is the Err
payload type.
Here's an example:
fn check(index: usize) -> Result<(), &'static str> {
if index > 42 {
Err("index is larger than 42")
} else {
Ok(())
}
}
Ok
and Err
are the same as Result::Ok
and Result::Err
. They are used so often that they are imported into your namespace by default, just like Result
itself is.
Despite this example, &'static str
isn't really a great default for the error payload. anyhow
may be a better place to start. (Good error design is a very large topic.)
There is also a convention where libraries or modules define their own aliases to Result
, usually replacing one or both of the generic types, such as the E
error payload type, with a specific type used throughout the library or module.
For example, std::io::Result<T>
is an alias for Result<T, std::io::Error>
and core::fmt::Result
is an alias for Result<(), core::fmt::Error>
. (As you can see, there is also a convention of naming your domain-specific error type Error
.)
The Result<()>
you refer to is one of these aliases.
When you need to disambiguate the different Result
types/aliases, you can refer to them via their module instead of importing their names, or you can import them under different names.
use std::fmt;
struct S;
impl fmt::Display for S {
// vvvvvvvvvvv
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
use std::fmt::{Display, Formatter, Result as FmtResult};
// ^^^^^^^^^^^^^^^^^^^
struct S;
impl Display for S {
// vvvvvvvvv
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Ok(())
}
}