Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.1k views
in Technique[技术] by (71.8m points)

rust - Is it possible to mark a potentially uninitialized variable as good without using unsafe or panicking?

Is it possible to explain to the compiler that the v variable is good at the line marked as 1 without using unsafe or code that may call 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
        }
        _ => {}
    }
}

The compiler reports:

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

I have a complex expression to initialize v in my real code instead of 17, the type of v does not implement Default, and I only need v for the Enum::V1 and Enum::V2 cases.

In the real code I have separate branches for Enum::V1 and Enum::V2, and I can move v initialization there.

I want to make my code more clear and I don't want to use potentially bad things like unsafe or Option::unwrap

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The simple method is to initialize v; it's a single word and the compiler can probably optimize it away if it is unnecessary. In this particular case, you could even move both the declaration and initialization into the inner scope of the match, because it isn't used anywhere else.

The cleaner thing to do is to make the invalid case unrepresentable. Here v only really exists in the cases V1 or V2, so if we join the two we don't have a name for a possibly uninitialized value.

#[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
        }
        _ => {}
    }
}

This is how types like Result and Option function.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...