I have this Rust code:
use std::fmt;
struct S {
a: i32,
b: i32,
c: Vec<String>,
}
impl fmt::Display for S {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.a {
-1 => {
if &self.b < &0 {
write!(f, "Invalid a & b\n")
} else {
write!(f, "Invalid a, valid b\n")
}
}
_ => write!(f, "Valid a & b\n"),
};
// not including this above semicolon causes an error
if &self.c.len() > &0 {
write!(f, "{}", &self.c.join("\n"))
} else {
write!(f, "")
}
}
}
fn main() {
let s = S {
a: 0,
b: 0,
c: vec![String::from("something")],
};
println!("{}", s)
}
The match is there to check whether arguments a
and b
are valid, and the if statement below is to check whether argument c
has at least 1 string in it to print out.
This code fails when I don't include a semicolon just after the match statement:
error[E0308]: mismatched types
--> src/main.rs:14:21
|
13 | / if &self.b < &0 {
14 | | write!(f, "Invalid a & b\n")
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `std::result::Result`
15 | | } else {
16 | | write!(f, "Invalid a, valid b\n")
17 | | }
| |_________________- expected this to be `()`
|
= note: expected unit type `()`
found enum `std::result::Result<(), std::fmt::Error>`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
help: try adding a semicolon
|
2 | ($ dst . write_fmt ($ crate :: format_args ! ($ ($ arg) *));)
| ^
help: consider using a semicolon here
|
17 | };
| ^
error[E0308]: mismatched types
--> src/main.rs:16:21
|
13 | / if &self.b < &0 {
14 | | write!(f, "Invalid a & b\n")
15 | | } else {
16 | | write!(f, "Invalid a, valid b\n")
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `std::result::Result`
17 | | }
| |_________________- expected this to be `()`
|
= note: expected unit type `()`
found enum `std::result::Result<(), std::fmt::Error>`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
help: try adding a semicolon
|
2 | ($ dst . write_fmt ($ crate :: format_args ! ($ ($ arg) *));)
| ^
help: consider using a semicolon here
|
17 | };
| ^
I am trying to make sense of what this error means. I know that semicolons are used to discard the result of an expression, and it seems by putting a semicolon after a match I am discarding the result of the match expression. Looking at the error message it says that it expected a ()
type instead of the type std::fmt::Result
on the lines where a write!
is performed.
- Why does it expect this
()
type, when all branches of the match statement and its inner if are callingwrite!
and returning astd::fmt::Result
? - When I don't include the second part of the code that checks the length of the argument
c
, suddenly the code works even without the semicolon. Why does it not error out without a semicolon when the second if that checks forc.len() > 0
is omitted?