为什么编译器假设if let的值应该是`()`?

时间:2016-06-05 20:32:31

标签: rust

我有以下代码:

use std::collections::HashSet;

fn translate() -> Option<String> {
    None
}

fn main() {
    let mut found = HashSet::new();

    if let Some(tr) = translate() {
        found.insert(tr);
    }
}

它工作正常,但是当我在found.insert(tr)之后删除分号时,出现编译错误:

error[E0308]: mismatched types
  --> src/main.rs:11:9
   |
7  | fn main() {
   |           - expected `()` because of default return type
...
11 |         found.insert(tr)
   |         ^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
   |         |
   |         expected (), found bool
   |
   = note: expected type `()`
              found type `bool`

此代码的位置或函数的最后一个表达式无关紧要。

为什么编译器会假设花括号内的表达式应该是()

2 个答案:

答案 0 :(得分:4)

根据Rust Book(强调我的):

  

表达式的值是选择的任何分支中最后一个表达式的值。没有if else始终会导致() 作为值。

这会对花括号内的表达式值进行约束。

这是正确的,因为表达式类型与()匹配:

if let Some(_) = some() {
    ()
};

这是正确的,因为else语句(以及分支之间的类型匹配):

if let Some(_) = some() {
    true
} else {
    false
};

但这是错误的:

if let Some(_) = some() {
    true
};

这个答案的灵感来自this comment

答案 1 :(得分:0)

当省略函数的返回类型时,该函数实际返回()。也就是说,

fn foo() {}

相当于:

fn foo() -> () {}
  

如果我添加return();在函数结束时,我仍然得到相同的错误。所以我甚至不确定这是否与函数返回值有关。

用作语句的if let表达式必须返回(),除非它是函数体中的最后一个表达式,在这种情况下,其类型必须与函数&#39相匹配; s返回类型。由于您的if let没有else条款,因此其类型必须为()