如何确保类型安全?

时间:2014-11-28 06:57:32

标签: rust

只是浏览the Rust guide(猜谜游戏),这段代码对我来说似乎不对:

let num = match input_num {
    Some(num) => num,
    None      => {
        println!("Please input a number!");
        continue;
    }
};

num的类型推断在这种情况下如何工作?第一个匹配案例显然返回一个数字,而第二个匹配案例只是println& continue语句,它不会返回任何内容(或返回())。编译器如何假设它的类型安全?

2 个答案:

答案 0 :(得分:15)

让我们更仔细地看一下这段代码:

loop {
    // ... some code omitted ...
    let num = match input_num {
        Some(num) => num,
        None      => {
            println!("Please input a number!");
            continue;
        }
    };
    // ... some code omitted ...
}

match语句位于循环内,语言中有几个构造可以帮助控制循环过程。 break提前退出循环,而continue跳过循环中的其余代码并返回其开头(重新启动它)。所以上面这个匹配基本上可以理解为“检查数字,如果它在那里,将其分配给num变量,否则输出一条消息并从头开始重启”。

“否则”分支的行为很重要:它以控制转移操作结束,在这种情况下为continue。编译器看到continue并知道循环将重新启动。因此,这个分支产生的价值并不重要,因为它永远不会被使用!它也许永远不会产生任何结果。

这种行为通常用所谓的bottom type建模,它是任何类型的子类型,根本没有值。 Rust没有子类型(基本上),所以这种类型非常神奇。它在类型签名中表示为!

fn always_panic() -> ! {
    panic!("oops!")
}

这个函数总是会引起恐慌,导致堆栈展开并最终终止它所调用的线程,所以它的返回值(如果有的话)永远不会被读取或以其他方式检查,所以绝对不能返回任何东西即使它在表达式上下文中使用,它需要一些具体的类型:

let value: int = always_panic();

因为always_panic()具有返回类型!,编译器知道它不会返回任何内容(在这种情况下因为always_panic()启动堆栈展开),允许它是安全的用于代替任何类型 - 毕竟,即使它在那里,价值永远不会被使用。

continue完全以相同的方式工作,但在本地。 None分支“返回”类型!,但Some分支返回某个具体数字类型的值,因此整个匹配语句属于此数字类型,因为编译器知道{{1分支将导致控制转移,其结果,即使它有一个,也永远不会被使用。

答案 1 :(得分:8)

continue以及breakreturn,"发散"。也就是说,编译器知道控制流不会在它之后恢复,它会转到其他地方。对于返回!的任何函数也是如此;这就是编译器知道像std::rt::begin_unwind这样的函数永远不会返回的原因。