Почему временная переменная подавляет ошибку «тип приписывается экспериментально»? - PullRequest
0 голосов
/ 02 ноября 2019

Я использую ящик JSON Serde для десериализации файла 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, пришедший из других языков. Я просто не понимаю эту ошибку, и я погуглил ее без какого-либо четкого объяснения. С моей точки зрения, исходя из других языков, я не вижу здесь никакой разницы и не понимаю, в чем заключалась проблема, которая была исправлена ​​или почему.

1 Ответ

3 голосов
/ 02 ноября 2019

Чтобы развернуть мой комментарий в ответ, введите ascription, когда тип переменной явно записывается с использованием двоеточия. Пример этого уже есть в вашем коде: config: Config, что означает, что config имеет тип Config. В большинстве случаев Rust может определить тип переменной на основе ее значения, поэтому определение типа не требуется. Фактически, за исключением нескольких особых случаев, приписывание типа даже не разрешено на этом языке (см. эту проблему ).

Основное место, где в настоящее время разрешено использование типа, этопри объявлении переменных. Это когда вы говорите что-то вроде let x: u32 = 7; или let mut s: String = "abc".to_string();. Аналогично, при определении структуры вы используете тип ascription для описания ее полей:

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

Другое основное место, которое может использовать (или должно) использовать тип ascription, - это аргументы функции и замыкания. Например,

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. Переназначение очень редко требует указания типа, поскольку не может изменить тип переменной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...