简体   繁体   English

在迭代中使用 Rust 中的通用 From-Trait

[英]Use generic From-Trait in Rust in Iteration

I try to write a simple postgres(=0.19.0) query function, which converts the Row to the Type which I need.我尝试编写一个简单的 postgres(=0.19.0) 查询 function,它将 Row 转换为我需要的 Type。

When I use a non generic Type it works without compile errors:当我使用非泛型类型时,它不会出现编译错误:

#[derive(Clone, Debug)]
struct Entry {
  id: u32,
  value: u32,
}

impl<'a> From<&'a Row> for Entry {
  fn from(row: &'a Row) -> Self {
    Entry {
      id: row.get(0),
      value: row.get(1),
    }
  }
}

fn query<'a, T: FromSql<'a>>(client: &mut Client, query_str: &str, params: &[&(dyn ToSql + Sync)]) -> Vec<Entry>  {
  client.query(query_str, params)
    .map(|rows| {
      rows
        .iter()
        .map(|r| {
          Entry::from(r)
        })
        .collect()
    })
    .unwrap_or(vec![] as Vec<Entry>)
}

When I try to convert the same logic in a generic way, I get a compile error.当我尝试以通用方式转换相同的逻辑时,出现编译错误。

fn query<'a, T: From<&'a Row>>(client: &mut Client, query_str: &str, params: &[&(dyn ToSql + Sync)]) -> Vec<T>  {
  let rows = client.query(query_str, params)
    .unwrap_or(vec![] as Vec<Row>);
  rows
    .iter()
    .map(|r: &'a Row| {
      T::from(r)
    })
    .collect()
}

I would say that the logic is equal and I can't see differences, but something isn't correct defined with the lifetime.我会说逻辑是平等的,我看不到差异,但是生命周期中的某些东西是不正确的。

Did I missed a Trait or something like that?我错过了一个特质或类似的东西吗?

    |
238 | fn query<'a, T: From<&'a Row>>(client: &mut Client, query_str: &str, params: &[&(dyn ToSql + Sync)]) -> Vec<T> {
    |          -- lifetime `'a` defined here
...
241 |       rows
    |       ^^^^ borrowed value does not live long enough
...
244 |           T::from(r)
    |           ---------- argument requires that `rows` is borrowed for `'a`
...
247 |     })
    |     - `rows` dropped here while still borrowed

Edit:编辑:

I simplified the code to this example, perhaps it is more helpful.我将代码简化为这个例子,也许它更有帮助。

fn convert<'a, T: From<&'a abc>>() -> Vec<T> {
    let abcs = vec![abc::new(), abc::new(), abc::new(), abc::new()];
    abcs
        .iter()
        .map(|f| {
            T::from(f)
        })
        .collect()
}

And here is the error:这是错误:

error[E0597]: `abcs` does not live long enough
  --> src/main.rs:43:5
   |
41 | fn convert<'a, T: From<&'a abc>>() -> Vec<T> {
   |            -- lifetime `'a` defined here
42 |     let abcs = vec![abc::new(), abc::new(), abc::new(), abc::new()];
43 |     abcs
   |     ^^^^ borrowed value does not live long enough
...
46 |             T::from(f)
   |             ---------- argument requires that `abcs` is borrowed for `'a`
...
49 | }
   | - `abcs` dropped here while still borrowed


what you are looking for is called a "Higher-Rank Trait Bound".您要查找的内容称为“高级特征绑定”。 (see here ) (见这里

for<'a> can be read as "for all choices of 'a", and basically produces an infinite list of trait bounds that F must satisfy for<'a> 可以读作“对于 'a 的所有选择”,并且基本上会生成 F 必须满足的特征边界的无限列表

this seems to be what you want, as you can specify a lifetime that is "smaller" than the lifetime of convert .这似乎是您想要的,因为您可以指定比convert的生命周期“更小”的生命周期。 in your example this would look like:在您的示例中,这看起来像:

fn convert< T: for<'a> From<&'a abc>>() -> Vec<T> {
    let abcs = vec![abc::new(), abc::new(), abc::new(), abc::new()];
    abcs
        .iter()
        .map(|f| {
            T::from(f)
        })
        .collect()
}

I've been trying to figure out the problem, but I can't.我一直试图找出问题所在,但我做不到。 Have you tried looking for any spelling errors?您是否尝试过查找任何拼写错误? I don't understand the code, but the reason I'm giving you an answer is because my friend might understand it.我不明白代码,但我给你答案的原因是因为我的朋友可能明白它。 Ok, so he says you might have missed a Trait, but he can't tell which one or what the problem is.好的,所以他说你可能错过了一个特质,但他无法判断是哪个特质或问题所在。 He suggests to look over it, I've forgot to add code to my programs before, and misspelled stuff.他建议检查一下,我之前忘记在我的程序中添加代码,并且拼写错误。 Looking over my code almost always helps me.查看我的代码几乎总是对我有帮助。

When you specify当您指定

fn convert<'a, T: From<&'a abc>>() -> Vec<T>

you are basically asserting that T implements From<&abc> only for those abc references that have a lifetime that outlives the function.您基本上是在断言T仅针对那些生命周期超过 functionabc引用实现From<&abc>

You may assume you function as having the following implicit lifetimes (here expressed in pseudocode):您可以假设您 function 具有以下隐式生命周期(此处以伪代码表示):

fn convert<'a, T: From<&'a abc>>() -> Vec<T> {
    'b : {
        let abcs = vec![abc::new(), abc::new(), abc::new(), abc::new()];
        abcs
            .iter()
            .map(|f| {
                T::from(f)
            })
            .collect()
    }
}

abcs belongs to an implicit lifetime "'b" that's smaller than 'a , and thus a reference to one of its elements can't satisfy From<&'a abc>> . abcs属于小于'a a 的隐式生命周期"'b" ,因此对其元素之一的引用不能满足From<&'a abc>> Given that you have to specify the lifetime when you constrain T: From<&'a abc> , there is no easy way out of this.鉴于您必须在约束T: From<&'a abc>时指定生命周期,因此没有简单的方法可以解决这个问题。

It makes sense for the compiler to reject this code because there's no way for it to ensure that From::from from T: From<&'a abc> won't generate a T that doesn't hold the reference it has been created from.编译器拒绝此代码是有意义的,因为它无法确保From::from from T: From<&'a abc>不会生成不包含已创建引用的 T从。

Something like the following would also be accepted by your function您的 function 也会接受类似以下内容

struct X<'a> {
    r: &' abc
}

impl <'a> From<&'a abc> for X<'a> {
    fn from(r: &'a abc) -> Self {
        Self { r }
    }
}

but it would be broken due to convert returning a Vec<X> that contains references to local instances of abc .但由于convert返回包含对abc本地实例的引用的Vec<X> ,它会被破坏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM