【问题标题】:Why must a I specify a lifetime when using a generic type reference in Rust? [duplicate]为什么在 Rust 中使用泛型类型引用时必须指定生命周期? [复制]
【发布时间】:2019-11-26 21:52:07
【问题描述】:

我正在为 serde_json::value::Value 引用实现 Rust 的 TryFrom 特征,以及一般将 Vec<Value> 转换为 Vec<T> 的函数,其中 T 实现 TryFrom<&Value>。因为我必须在我的函数中为Value 引用指定生命周期,所以我无法返回T::try_from 的结果(借用值被丢弃)。

我尝试了另一种可行的方法;创建我自己的特征,类似于TryFrom,但没有泛型。这可行,但我不明白为什么我不能使用 TryFrom 和泛型,因为特征已经存在。

我的通用代码引发编译时错误:

impl TryFrom<&Value> for Channel {
    type Error = &'static str;

    fn try_from(value: &Value) -> Result<Self, Self::Error> {
        let title = value.get("title").ok_or("couldn't find title property in json")?
            .as_str().ok_or("title was not a string")?;
        let name = value.get("user_name").ok_or("couldn't find user_name property in json")?
            .as_str().ok_or("user_name was not a string")?;

        Ok(Channel {
            title: String::from(title),
            user_name: String::from(name)
        })
    }
}

// I must add a lifetime below. Please ignore the self reference.
fn get_many_generic<'a, T: TryFrom<&'a Value>>(&self, url_str: &str) -> Result<Vec<T>, Box<dyn std::error::Error>> {
    // perform_get returns a serde_json::Value
    let mut value = &self.perform_get(url_str)?;

    if let Value::Object(map) = value {
        value = map.get("data").ok_or("found a map without a 'data' property when expecting an array")?;
    }

    if let Value::Array(vec) = value {
        Ok(vec.iter()
            .filter_map(|item|
                match T::try_from(item) {
                    Ok(model) => Some(model),
                    Err(e) => {
                        println!("Could not deserialize value {}", item);
                        None
                    }
                }
            ).collect())
    }
    else {
        Err(Box::new(
            Error::new(format!("Expected array from {}, but didn't receive one.", url_str))
        ))
    }
}

我的代码有效:

pub trait TryFromValue where Self: std::marker::Sized {
    fn try_from_value(value: &Value) -> Result<Self, Box<dyn Error>>;
}

impl TryFromValue for Channel {
    fn try_from_value(value: &Value) -> Result<Channel, Box<dyn Error>> {
        let title = value.get("title").ok_or("couldn't find title property in json")?
            .as_str().ok_or("title was not a string")?;
        let name = value.get("user_name").ok_or("couldn't find user_name property in json")?
            .as_str().ok_or("user_name was not a string")?;

        Ok(Channel {
            title: String::from(title),
            user_name: String::from(name)
        })
    }
}

fn get_many<T: TryFromValue>(&self, url_str: &str) -> Result<Vec<T>, Box<dyn std::error::Error>> {
    // perform_get returns a serde_json::Value
    let mut value = &self.perform_get(url_str)?;

    if let Value::Object(map) = value {
        value = map.get("data").ok_or("found a map without a 'data' property when expecting an array")?;
    }

    if let Value::Array(vec) = value {
        Ok(vec.iter()
            .filter_map(|item|
                match T::try_from_value(item) {
                    Ok(model) => Some(model),
                    Err(e) => {
                        println!("Could not deserialize value {}. Error {}", item, e);
                        None
                    }
                }
            ).collect())
    }
    else {
        Err(Box::new(
            Error::new(format!("Expected array from {}, but didn't receive one.", url_str))
        ))
    }
}

为什么这种方法行得通,但第一个代码示例失败了?

【问题讨论】:

  • 第一段代码的错误信息是什么?很难回答这个问题,因为当我编译它时,我收到一堆关于缺少导入和不正确的 &amp;self 参数的错误,但我不知道 看到了什么。请尝试创建一个minimal reproducible example,最好是the playground
  • 应用于你的问题,看起来像fn get_many_generic&lt;T: for&lt;'a&gt; TryFrom&lt;&amp;'a Value&gt;&gt;(...)
  • @trentcl 你说得对,这解决了我的问题。我想是时候重新阅读 Rustnomicon 中的那一章了。谢谢!也很抱歉发布了一个骗局。
  • 没有理由感到抱歉!重复的问题有时很有用;它们可以链接在一起,以帮助未来的提问者更轻松地找到答案。很高兴我能提供帮助!

标签: generics reference rust serde


【解决方案1】:

更高等级的特征界限(由 trentcl 建议)修复了这个问题。查看他们的评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2016-12-02
    • 1970-01-01
    • 2018-02-12
    • 2020-10-11
    • 2019-04-08
    相关资源
    最近更新 更多