是否有可能将未初始化的潜在变量标记为好而不使用不安全或恐慌?

时间:2017-07-28 10:26:31

标签: rust

是否可以向编译器解释v变量在标记为1的行中是否合适,而不使用可能调用panic!的不安全或代码?

#[derive(PartialEq, Debug)]
enum Enum {
    V1,
    V2,
    V3,
}

fn main() {
    let e = Enum::V1;

    let mut v: i32;

    if e == Enum::V1 || e == Enum::V2 {
        v = 17; //some complex, costy expression
    }
    match e {
        Enum::V1 | Enum::V2 => {
            println!("Results: {}", v); //1
        }
        _ => {}
    }
}

编译器报告:

error[E0381]: use of possibly uninitialized variable: `v`
  --> src/main.rs:18:37
   |
18 |             println!("Results: {}", v); //1
   |                                     ^ use of possibly uninitialized `v`

我有一个复杂的表达式来初始化我的真实代码中的v而不是17v的类型没有实现Default,我只需要{{ 1}}适用于vEnum::V1个案例。

在实际代码中,我有Enum::V2Enum::V1的单独分支,我可以在那里进行Enum::V2初始化。

我想让我的代码更清晰,而且我不想使用vunsafe

等潜在的错误内容

2 个答案:

答案 0 :(得分:5)

简单的方法是初始化v;这是一个单词,如果没有必要,编译器可能会优化它。在这种特殊情况下,您甚至可以将声明和初始化都移动到匹配的内部范围中,因为它不会在其他任何地方使用。

更干净的事情是使无效案件无法代表。 v仅在V1V2的情况下才真正存在,因此如果我们加入这两个,我们就没有可能未初始化的值的名称。

#[derive(PartialEq, Debug)]
enum Enum {
    V1 { v: i32 },
    V2 { v: i32 },
    V3
}

fn main() {
    let mut e = Enum::V1 { v: 17 };

    match e {
        Enum::V1 {v} | Enum::V2 {v} => {
            println!("Results: {}", v);//1
        }
        _ => {}
    }
}

这就是ResultOption等类型的功能。

答案 1 :(得分:4)

在安全的Rust中,你不能。在您的代码中,v仅保证在条件分支e == Enum::V1 || e == Enum::V2下初始化,但v在更广泛的范围内声明。请注意,这不是限制,而是来自编译器的提示,应该重新考虑程序的设计。

在这种情况下,我会将v的计算委托给一个函数,并且在必要的案例块中只有v

fn calculate_v(e: Enum) -> i32 { ... }

let e = Enum::V1;

match e {
    Enum::V1 => {
        let v = calculate_v(e);
        // use v
        println!("Results: {}", v);//1
    }
    Enum::V2 => {
        let v = calculate_v(e);
        println!("Results: {}", v);//1
    }
    _ => {}
}