Rust 如何保证类型安全?

Rust 如何保证类型安全?,rust,Rust,只是浏览一下(猜谜游戏),我觉得这个代码片段不合适: let num = match input_num { Some(num) => num, None => { println!("Please input a number!"); continue; } }; 在这种情况下,num的类型推断是如何工作的?第一个匹配用例显然返回一个数字,而第二个匹配用例只是println&continue语句,它不返回任何内容(

只是浏览一下(猜谜游戏),我觉得这个代码片段不合适:

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

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

continue
break
return
是“发散的”。也就是说,编译器知道控制流不会在它之后恢复,而是转到其他地方。任何返回
的函数也是如此;这就是编译器如何知道像
std::rt::begin\u unwind
这样的函数永远不会返回的原因。

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

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
,知道循环将重新启动。因此,这个分支产生的价值并不重要,因为它永远不会被使用!它还不如什么也不做

这种行为通常使用所谓的模型来建模,它是任何类型的子类型,并且根本没有值。锈菌没有亚型(本质上),所以这种类型非常神奇。它被表示为
在类型签名中:

fn always_panic() -> ! {
    panic!("oops!")
}
此函数总是死机,这会导致堆栈展开和调用它的线程的最终终止,因此它的返回值(如果有)将永远不会被读取或以其他方式检查,因此完全不返回任何内容是绝对安全的,即使它被用在需要某种具体类型的表达式上下文中:

let value: int = always_panic();
因为
总是\u panic()
有返回类型
,编译器知道它不会返回任何东西(在这种情况下,因为
总是\u panic()
启动堆栈展开),允许它代替任何类型使用是安全的-毕竟,该值即使存在,也永远不会被使用


continue
的工作方式完全相同,但仅限于本地<代码>无
分支“返回”类型
,但是,
Some
分支返回某个具体数值类型的值,因此整个match语句都是这种数值类型的,因为编译器知道
None
分支将导致控制传输,并且其结果(即使有)将永远不会被使用。

我们似乎没有相同的类型安全定义。这里您似乎在谈论类型推断(猜测正确的类型),而类型安全性是一种语言的属性,它阻止您观察给定类型的值,就像它是另一个不相关的类型一样;类型不安全的典型示例是C的
void*
。从新手的角度来看,匹配表达式的第一种情况返回“num”(即uint值),而第二种匹配表达式返回“()”(因为,块以“;”)结尾,在我看来,代码混合了两种不同的类型(uint类型和()类型)我理解你的观点,但这并不意味着这不是类型安全的,只要在本例中,编译器将
num
的类型记录为
uint
()
,并且只允许相关操作。当然,正如答案中所解释的(但不是你在学习之前可以知道的),它实际上更神奇:)注意,
是通常称为底部的文献,请参阅。