【问题标题】:Is this "possibly-uninitialized" compiler error a false alarm? [rustc 1.51.0]这个“可能未初始化”的编译器错误是误报吗? [锈病 1.51.0]
【发布时间】:2021-04-04 23:55:34
【问题描述】:

我遇到了 possibly-uninitialized variable 错误,尽管我确信这绝不应该是这种情况。
(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-blocks 不是“好的风格”恕我直言):

  • 由于discriminant 是不可变的,我希望第二个if 块在没有第一个块的情况下永远不会执行。
  • 因此,应始终在借用 println!() 时定义变量。

可能的缓解措施

可以通过使用临时值初始化 value 来“消除”错误。
我强烈反对这种方法,因为

  • 由于无法在其他代码路径中计算,临时值在数学意义上可能是错误的。
  • 此外,这可能会隐藏在开发过程中未正确定义值这一事实,从而限制编译器发出错误信号的能力。

问题

有人可以澄清这种情况是预期行为还是编译器错误?

【问题讨论】:

  • 代码当然没问题。在编译器中,关于未初始化变量的警告在这种情况下出现误报是很正常的,这就是为什么它说“可能”的原因。没有办法在所有情况下都有 100% 正确的警告,因为这是停止问题。

标签: rust compiler-errors compiler-bug


【解决方案1】:

您不是第一个看到这种行为的人,通常我不会认为这是一个错误。在你的情况下,条件非常简单和明显,你我很容易推理出这个条件。但是,一般情况下,条件不需要很明显,例如,第二种情况可能有其他难以推理的条件,即使代码是正确的。

此外,您希望编译器执行的分析(根据条件确定可以访问的代码)通常仅在编译器进行优化时进行。因此,即使编译器支持这种分析,它也可能无法在调试模式下工作。即使在最好的优化编译器和静态分析工具中,它也并非在所有情况下都有效。

如果您对在这种情况下初始化一个虚拟值有哲学上的反对意见,您可以使用Option

fn example(discriminant: bool) {
    let value = if discriminant {
        Some(0)
    } else {
        None
    };

    // more code [...]

    if discriminant {
        println!("{}", value.unwrap());
    }
}

在这种情况下,您的值始终被初始化,并且在第二部分中,您断言它包含合适的非None 值。如果您处于发布模式,编译器可能能够确定您的代码是正确的并对其进行优化以省略Option(或者可能不会)。

【讨论】:

  • let value = discriminant.then(|| 0); ... if let Some(v) = value { ... }
  • 当然,我会把它写成if let Some(v),但这确实与我写的不同,我故意选择让它与原始代码相似。虽然您可以使用bool::then,但它相对较新,即使它适用于 OP,我更喜欢编写更兼容的代码来帮助不使用最新 Rust 的人.
  • 谢谢,我了解到一般情况下编译器是解决不了这个问题的!你的例子清楚地表明我基本上可以使用一个选项而不是一些哨兵值。
  • 我认为由于引入了优化器,这个答案令人困惑。流敏感类型检查(或者在这种情况下,活性检查)存在,Rust 已经部分支持它——你可以在循环中看到它的作用。优化器实际上与此无关。
猜你喜欢
  • 2013-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
相关资源
最近更新 更多