为什么临时变量会抑制“类型归因于实验”错误?

时间:2019-11-02 16:46:35

标签: compiler-errors rust

我正在使用Serde JSON板条箱将JSON文件反序列化为结构,并且其中一个属性是可选的。当属性缺少默认值(从命令行)时,它将被替换。这导致我修改代码,从而引发以下错误,并且很难弄清楚如何解决它。

我的问题是,除非将值分配给临时变量,否则我将得到type ascription is experimental error,但我不明白为什么。我将展示代码,并忽略Config的结构,因为我认为这并不重要。

这是有效的代码:

    pub fn new(file_name: &str, param_urls: &[String]) -> Result<Config, io::Error> {
        let mut config: Config = Config {
            queue: None
        };
        if Path::new(file_name).exists() {
            let json = read_to_string(file_name)?;
            let c: Config = serde_json::from_str(&json)?;
            config = c;
            // ^^^^^^^ must use temporary c variable
        }
        if config.queue.is_none() {
            config.queue = Some(param_urls.to_vec());
        }
        Ok(Config {
            queue: None
        })
    }

上面的代码花了我一段时间,我不明白为什么它可以解决错误,但是这里是引发错误的原始源代码。

    pub fn new(file_name: &str, param_urls: &[String]) -> Result<Config, io::Error> {
        let mut config: Config = Config {
            queue: None
        };
        if Path::new(file_name).exists() {
            let json = read_to_string(file_name)?;
            config: Config = serde_json::from_str(&json)?;
            // ^^^^^^^^^^^ ERROR! type ascription is experimental error
        }
        if config.queue.is_none() {
            config.queue = Some(param_urls.to_vec());
        }
        Ok(Config {
            queue: None
        })
    }

作为来自其他语言的新Rust程序员。我根本不理解此错误,并且在没有任何明确解释的情况下对Google进行了搜索。从我的角度来看,我来自其他语言,在这里看不到任何区别,也不了解解决了什么问题或原因。

1 个答案:

答案 0 :(得分:3)

要将我的评论扩展为答案,请在使用冒号显式表示变量的类型时键入归因。这样的示例已经存在于您的代码中:config: Config,这意味着config的类型为Config。大多数时候,Rust能够根据变量的值推断出变量的类型,因此不需要类型说明。实际上,除少数特殊情况外,该语言甚至还不允许输入类型说明(请参见this issue)。

现在允许类型归类的主要地方是在声明变量时。这是当您说诸如let x: u32 = 7;let mut s: String = "abc".to_string();之类的内容时。同样,在定义结构时,可以使用type ascription来描述其字段:

struct Foo {
    bar: Vec<i32>,
    baz: String,
}

可以(或必须)使用类型说明的另一个主要地方是在函数和闭包参数中。例如

fn add_one(x: u64) -> u64 {
    x + 1
}

let f = |t: String| t + "123"。使用闭包时,通常可以根据闭包的使用方式来推断变量的类型,但有时对编译器或读者明确声明参数的类型很有帮助。

在您的特定情况下,您将类型归因用于重新分配操作,该操作目前不属于允许类型归因的任何类别。 config: Config = serde_json::from_str(&json)?;可以毫无问题地更改为config = serde_json::from_str(&json)?;,因为编译器已经知道config的类型为Config。重新分配很少需要类型归属,因为它不能更改变量的类型。