【问题标题】:Shouldn't the `return` statement return `!` (never type)?`return` 语句不应该返回 `!` (从不输入)吗?
【发布时间】:2022-01-25 14:12:26
【问题描述】:

示例代码sn-p:

fn foo() -> i32 {
    let a = return 2;
    a + 1
}
fn main() {
    println!("{}", foo());
}

我希望因为a 永远不会真正被分配任何东西,它的类型应该是!。但是编译器告诉我它的类型实际上是()(单位类型)。这让我觉得很奇怪。这可能是什么原因?

【问题讨论】:

    标签: rust return


    【解决方案1】:

    return 42的类型!:

    breakcontinuereturn 表达式也有 ! 类型。例如我们可以这样写:

    #![feature(never_type)]
    let x: ! = {
        return 123
    };
    

    来自https://doc.rust-lang.org/std/primitive.never.html

    ! 的一个特点是它可以强制转换为任何类型的值:

    fn foo() -> i32 {
        let a: String = return 2;
        42
    }
    
    fn main() {
        println!("{}", foo());
    }
    

    这就是使之类的事情发生的原因

    let num: u32 = match get_a_number() {
        Some(num) => num,
        None => break,
    };
    

    (来自同一页面)。

    两个分支必须具有相同的类型。 num 显然是 u32break!。然后,通过将 break 强制转换为 u32,两者都可以具有相同类型的 u32

    这很好,因为 ! 类型的值永远不会存在,因此编译器可以将其“转换”为任何其他类型的任何值。

    在您的示例中出现混淆的地方是编译器将声明“错误[E0277]:无法将i32 添加到()”。这可能是出于历史原因。 ! 在 Rust 1.0 时代并没有这样存在。随着时间的推移,它变得更像一等公民,但为了向后兼容需要一些特殊情况,其中! 将被视为() 而不是任何其他类型。

    【讨论】:

    • OP 是否启用了 never_type 功能?根据 never_type RFC,以前可以为此类表达式分配类型 ()。
    • 该功能只允许您显式使用 never 类型。无论您是否启用它,在这种情况下,行为和错误消息都是相同的,以实现向后兼容性。
    • 好的,我明白了。
    猜你喜欢
    • 1970-01-01
    • 2010-11-01
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    相关资源
    最近更新 更多