结果和if / else / return语句E0308错误

时间:2018-06-26 18:54:49

标签: if-statement rust return

为什么以下代码在编译时会引发错误?

fn test(n: i32) -> Result<i32, &'static str> {
    if n == 0 {
        Err("error")
    }
    Ok(n + 1)
}

以下是错误:

error[E0308]: mismatched types
  --> src/main.rs:41:9
   |
41 |         Err("error")
   |         ^^^^^^^^^^^^- help: try adding a semicolon: `;`
   |         |
   |         expected (), found enum `std::result::Result`
   |
   = note: expected type `()`
              found type `std::result::Result<_, &str>`

以下两个版本可以毫无问题地编译。

  1. 带有else语句:

    fn test(n: i32) -> Result<i32, &'static str> {
        if n == 0 {
            Err("error")
        }
        else {
            Ok(n + 1)
        }
    }
    
  2. 带有return语句:

    fn test(n: i32) -> Result<i32, &'static str> {
        if n == 0 {
            return Err("error");
        }
        Ok(n + 1)
    }
    

我正在使用Rust 1.27.0。

1 个答案:

答案 0 :(得分:4)

想象一下这个简化的代码:

fn test() -> i32{
    { 1 }
    2
}

此操作失败,并显示以下错误:

error[E0308]: mismatched types
 --> src/main.rs:2:11
  |
2 |         { 1 }
  |           ^ expected (), found integral variable
  |
  = note: expected type `()`
             found type `{integer}`

这是因为在Rust中,完整的语句必须具有类型()。如果要忽略值,只需添加;即可将值转换为语句,然后将类型更改为()并丢弃该值。

此代码编译:

fn test() -> i32{
    { 1; }
    2
}

您的示例与此类似,但是if使事情变得更加有趣。如果您写:

fn test(c: bool) -> i32{
    if c { 1 }
    2
}

它将失败,就像以前一样,因为第一条语句的类型不同于()。添加;可解决此问题:

fn test(c: bool) -> i32{
    if c { 1; }
    2
}

else也会编译,因为在函数中只有一个语句,并且其类型与函数的返回类型匹配:

fn test(c: bool) -> i32{
    if c { 1 }
    else { 2 }
}

请注意,两个分支必须具有相同的类型,并且两个分支中均不得包含;

添加return也是可以的,因为return语句在定义上具有(),因此其中任何一个都可以编译:

fn test1(c: bool) -> i32{
    if c { return 1; }
    2
}
fn test2(c: bool) -> i32{
    if c { return 1 }
    2
}
fn test3(c: bool) -> i32{
    if c { return 1; }
    else { 2 }
}
fn test4(c: bool) -> i32{
    if c { return 1; }
    else { return 2; }
}

请注意,在这些;语句中,return实际上是可选的,因为它已经是()类型。