Как я подразумеваю тип значения, когда нет параметров типа или атрибутов?

Я пытаюсь преобразовать мою структуру в HashMap, но я не могу это сделать, находясь в блоке impl. Из-за ограничения ящика я могу использовать только &self в качестве параметра для resolve функция.

use std::collections::HashMap;

pub enum Value {
    Int(i64),
    Object(HashMap<String, Value>),
}

pub struct WeatherSettings {
    forecast_days: i64,
}

impl WeatherSettings {
    fn resolve(&self) -> Value {
        let json_object: HashMap<String, Value> = *self.into();
        Value::Object(json_object)
    }
}

impl From<WeatherSettings> for HashMap<String, Value> {
    fn from(weather: WeatherSettings) -> HashMap<String, Value> {
        let mut json_object = HashMap::new();
        json_object.insert("forecast_days".to_owned(),
                           Value::Int(weather.forecast_days));
        return json_object;
    }
}

fn main() {}

Проще говоря, я получаю ошибку:

error: the type of this value must be known in this context
  --> src/main.rs:14:51
   |
14 |         let json_object: HashMap<String, Value> = *self.into();
   |                                                   ^^^^^^^^^^^^

1 ответ

Решение

Как мне подразумевать тип значения, когда нет параметров типа или атрибутов?

В подавляющем большинстве случаев компилятор Rust может вывести универсальные типы типа или функции на основе того, как используются значения универсального типа.

В некоторых случаях недостаточно информации, чтобы вывести ровно один тип для универсального типа, но всегда есть способ передать параметры типа, когда они существуют.

Два способа сделать это - использовать turbofish или полностью определенный синтаксис на сайте вызова.

Turbofish

TurboFish это символы ::<Type1, Type2, ...> добавляется к функции или типу. Видишь как выглядит рыба?

Пример функции

mem::size_of определяется как:

pub const fn size_of<T>() -> usize.

Вы можете назвать это как:

std::mem::size_of::<i8>()
//               ^^^^^^ turbofish

Пример типа

Vec::new определяется как:

impl<T> Vec<T> {
    pub fn new() -> Vec<T>
}

Вы можете назвать это как:

Vec::<u8>::new()
// ^^^^^^ turbofish

Несколько типов

Если ваша функция имеет несколько типов, вам нужно указать что-то для каждого типа в том же порядке, что и определение:

fn example<A, B>() {}

fn main() {
    example::<i32, bool>();
    //         ^A  ^B
}

Полностью определенный синтаксис

Если вам необходимо устранить неоднозначность вызова метода для определенной характеристики с параметром типа, вы можете использовать полный синтаксис.

From::from определяется как:

trait From<T> {
    fn from(T) -> Self;
}

Вы можете назвать это как:

    <String as From<&str>>::from("a")
//  ^^^^^^^^^^^^^^^^^^^^^^ fully qualified syntax

Частично выведенные типы

Если есть несколько типов, которые могут быть предоставлены, но некоторые из них могут быть выведены, вы все равно можете использовать _ чтобы позволить компилятору выводить этот конкретный тип.


Здесь я использую турбовину на Into введите код:

let json_object = *Into::<HashMap<String, Value>>::into(self);

Это не твоя проблема, хотя.

Чтобы эта строка была действительной:

let json_object: HashMap<String, Value> = *self.into();

Результат звонка self.into() должно быть что-то, что может быть разыменовано для получения типа HashMap<String, Value>, Как компилятор должен знать, что это такое? Это также не то, что вы хотите.

Все что у вас есть &self, так что это то, что вы должны конвертировать из. Реализуйте черту для ссылки на вашу структуру:

impl<'a> From<&'a WeatherSettings> for HashMap<String, Value> {
    fn from(weather: &'a WeatherSettings) -> HashMap<String, Value> {
        let mut json_object = HashMap::new();
        json_object.insert("unit".to_owned(), Value::String(weather.unit.clone()));
        json_object.insert("forecast_days".to_owned(), Value::Int(weather.forecast_days));
        json_object.insert("data".to_owned(), Value::String(weather.data.clone()));
        json_object
    }
}

Это означает, что вы не можете переместить строки, а должны скопировать их. Это ограничение, наложенное &self,

Другие вопросы по тегам