这个 "possibly-uninitialized" 编译器错误是误报吗? [生锈 1.51.0]
Is this "possibly-uninitialized" compiler error a false alarm? [rustc 1.51.0]
我遇到了 可能未初始化的变量 错误,尽管我确信这永远不会是这种情况。
(rustc --version 是 rustc 1.51.0 (2fd73fabe 2021-03-23)
)
fn example(discriminant: bool) {
let value;
if discriminant {
value = 0;
}
// more code [...]
if discriminant {
println!("{}", value);
}
}
错误信息如下:
error[E0381]: borrow of possibly-uninitialized variable: `value`
--> src/raytracing/intersect.rs:8:24
|
10 | println!("{}", value);
| ^^^^^ use of possibly-uninitialized `value`
推理
我确实希望示例能够编译(即使如图所示分隔 if
块不是“好的风格”恕我直言):
- 由于
discriminant
是不可变的,我希望第二个 if
块在没有第一个的情况下永远不会执行。
- 因此,变量应始终在
println!()
中借用时定义。
可能的缓解措施
可以通过使用临时值初始化 value
来 'silenced' 错误。
我强烈反对这种做法,因为
- 临时值在数学意义上可能是错误的,因为它无法在其他代码路径中计算。
- 此外,这可能会掩盖在开发过程中未正确定义该值的事实,从而限制编译器发出错误信号的能力。
问题
有人可以澄清这种情况是预期行为还是编译器错误?
您不是第一个看到此行为的人,通常我不会将其视为错误。在你的情况下,条件非常简单明了,你我很容易推理出这个条件。但是,一般情况下,条件不需要很明显,例如,第二种情况可能有其他难以推理的条件,即使代码是正确的。
此外,您希望编译器进行的那种分析(根据条件确定哪些代码可以访问)通常仅在编译器进行优化时进行。因此,即使编译器支持这种分析,它也可能无法在调试模式下工作。即使在最好的优化编译器和静态分析工具中,它也并非在所有情况下都有效。
如果您对在这种情况下初始化虚拟值有哲学上的反对意见,您可以使用 Option
:
fn example(discriminant: bool) {
let value = if discriminant {
Some(0)
} else {
None
};
// more code [...]
if discriminant {
println!("{}", value.unwrap());
}
}
在这种情况下,您的值始终被初始化,并且在第二部分中,您断言它包含一个合适的非 None
值。如果您处于发布模式,编译器可能能够确定您的代码是正确的并对其进行优化以省略 Option
(或者可能不会)。
我遇到了 可能未初始化的变量 错误,尽管我确信这永远不会是这种情况。
(rustc --version 是 rustc 1.51.0 (2fd73fabe 2021-03-23)
)
fn example(discriminant: bool) {
let value;
if discriminant {
value = 0;
}
// more code [...]
if discriminant {
println!("{}", value);
}
}
错误信息如下:
error[E0381]: borrow of possibly-uninitialized variable: `value`
--> src/raytracing/intersect.rs:8:24
|
10 | println!("{}", value);
| ^^^^^ use of possibly-uninitialized `value`
推理
我确实希望示例能够编译(即使如图所示分隔 if
块不是“好的风格”恕我直言):
- 由于
discriminant
是不可变的,我希望第二个if
块在没有第一个的情况下永远不会执行。 - 因此,变量应始终在
println!()
中借用时定义。
可能的缓解措施
可以通过使用临时值初始化 value
来 'silenced' 错误。
我强烈反对这种做法,因为
- 临时值在数学意义上可能是错误的,因为它无法在其他代码路径中计算。
- 此外,这可能会掩盖在开发过程中未正确定义该值的事实,从而限制编译器发出错误信号的能力。
问题
有人可以澄清这种情况是预期行为还是编译器错误?
您不是第一个看到此行为的人,通常我不会将其视为错误。在你的情况下,条件非常简单明了,你我很容易推理出这个条件。但是,一般情况下,条件不需要很明显,例如,第二种情况可能有其他难以推理的条件,即使代码是正确的。
此外,您希望编译器进行的那种分析(根据条件确定哪些代码可以访问)通常仅在编译器进行优化时进行。因此,即使编译器支持这种分析,它也可能无法在调试模式下工作。即使在最好的优化编译器和静态分析工具中,它也并非在所有情况下都有效。
如果您对在这种情况下初始化虚拟值有哲学上的反对意见,您可以使用 Option
:
fn example(discriminant: bool) {
let value = if discriminant {
Some(0)
} else {
None
};
// more code [...]
if discriminant {
println!("{}", value.unwrap());
}
}
在这种情况下,您的值始终被初始化,并且在第二部分中,您断言它包含一个合适的非 None
值。如果您处于发布模式,编译器可能能够确定您的代码是正确的并对其进行优化以省略 Option
(或者可能不会)。