簡體   English   中英

Rust 中的不同功能有什么意義?

[英]What is the point of diverging functions in Rust?

我已經閱讀了幾個關於 SO 的答案,並收集了這些用例:

  • 當一個 function panic! s
  • 當 function 中有一個無限循環時

但我仍然不清楚為什么我們需要像這樣定義 function:

fn func() -> ! {
    panic!("Error!");
}

如果它的工作方式與此相同(沒有感嘆號):

fn func() {
    panic!("Error!");
}

同時,為什么我們需要使用! 在具有無限循環的函數中? 看起來這個簽名並沒有帶來任何真實的使用信息。

這些簽名之間的主要區別歸結為一個事實! 可以強制轉換為任何其他類型,因此與任何其他類型兼容(由於從未采用此代碼路徑,我們可以假設它是我們需要的任何類型)。 當我們有多個可能的代碼路徑時,這一點很重要,例如if-elsematch

例如,考慮以下(可能是人為的,但希望足夠清晰)代碼:

fn assert_positive(v: i32) -> u32 {
    match v.try_into() {
        Ok(v) => v,
        Err(_) => func(),
    }
}

func被聲明返回時! ,這個function 編譯成功。 如果我們刪除返回類型, func將被聲明為返回() ,並且編譯中斷

error[E0308]: `match` arms have incompatible types
 --> src/main.rs:8:19
  |
6 | /     match v.try_into() {
7 | |         Ok(v) => v,
  | |                  - this is found to be of type `u32`
8 | |         Err(_) => func(),
  | |                   ^^^^^^ expected `u32`, found `()`
9 | |     }
  | |_____- `match` arms have incompatible types

您還可以將其與Result::unwrap的定義進行比較:

pub fn unwrap(self) -> T {
    match self {
        Ok(t) => t,
        Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e),
    }
}

在這里, unwrap_failed正在返回! ,因此它與Ok情況下返回的任何類型相統一。

編譯器知道遵循發散表達式(w.r.t. 評估順序)的任何內容都是不可達的。 在決定是否初始化局部變量時,它可以使用此信息來避免誤報。

考慮以下示例:

use rand; // 0.8.4

fn main() {
    let foo;
    if rand::random::<bool>() {
        foo = "Hello, world!";
    } else {
        diverge();
    }
    println!("{foo}");
}

fn diverge() {
    panic!("Crash!");
}

我們聲明了一個變量foo ,但我們只在if表達式的一個分支中初始化它。 這無法編譯並出現以下錯誤:

error[E0381]: borrow of possibly-uninitialized variable: `foo`
  --> src/main.rs:10:15
   |
10 |     println!("{foo}");
   |               ^^^^^ use of possibly-uninitialized `foo`

但是,如果我們像這樣改變我們的diverge function 的定義:

fn diverge() -> ! {
    panic!("Crash!");
}

然后代碼成功編譯。 編譯器知道如果使用else分支,它永遠不會到達println! 因為diverge()發散。 因此, else分支沒有初始化foo並不是錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM