【问题标题】:What happens when a Rust struct contains a lifetimed trait?当 Rust 结构包含生命周期特征时会发生什么?
【发布时间】:2019-02-24 22:04:01
【问题描述】:

好的,所以我是个 Rust 新手,我正在试验 Rocket。该 Web 框架传递了一个 Form<MyStruct>,我想将该 MyStruct 转移到我自己的自定义结构中。

struct Consumer<T> {
    d: T,
}

impl<T> Consumer<T> {
   fn new(form: Form<T>) -> Self {
       Consumer { d: form.into_inner() }
   }
}

这当然行不通,我明白了:

the trait `rocket::request::FromForm<'_>` is not implemented for `T`

下一次尝试:

impl<T> Consumer<T> where T: FromForm {
    fn new(form: Form<T>) -> Self {
        Consumer { d: form.into_inner }
    }
}

哦哦:

impl<T> Consumer<T> where T: FromForm {
                             ^^^^^^^^ expected lifetime parameter

所以现在我发现自己完全无法解决这个问题!我能想到的最好的是:

impl<'f, T> Consumer<T> where T: FromForm<'f> {
    fn new(form: Form<T>) -> Self {
        Consumer { d: form.into_inner }
    }
}

但这会导致这个错误:

51 |           fn new(form: Form<T>) -> Self {                                                                                      
   |  _________^                                                                                                                    
52 | |             Consumer { d: form.into_inner }                                                                                  
53 | |         }                                                                                                                    
   | |_________^ lifetime mismatch
  = note: expected type `rocket::request::FromForm<'_>`                                                                            
             found type `rocket::request::FromForm<'f>`

可验证示例:https://hastebin.com/eqihaqodux.makefile

【问题讨论】:

  • 欢迎来到 Stack Overflow!请确保您提供了您要实现的目标的minimal reproducible example。这包括提及您如何获得FormFromForm(假设它们来自Rocket,您需要包括use语句)。第一个错误消息也可以扩展为看起来像其他两个(因此包括行号等)。

标签: rust traits lifetime


【解决方案1】:

Form 也有一个生命周期参数。如果你将它与FromForm 的生命周期联系起来,那么你会前进一点:

impl<'f, T> Consumer<T> where T: FromForm<'f> {
    fn new(form: Form<'f, T>) -> Self {
        Consumer(form.into_inner())
    }

    fn get(&self) -> &T {
        &self.0
    }
}

作为一般规则,如果您返回的对象依赖于另一个对象中的数据,那么您需要像这样将它们的生命周期链接在一起。

此时,您会看到另一个错误,它可以方便地为您提供修复它所需的所有信息:

error[E0310]: the parameter type `T` may not live long enough
  --> src/main.rs:50:17
   |
48 | impl<'f, T> Consumer<T> where T: FromForm<'f> {
   |          - help: consider adding an explicit lifetime bound `T: 'static`...
49 |     fn new(form: Form<'f, T>) -> Self {
50 |         Consumer(form.into_inner())
   |                       ^^^^^^^^^^
   |
note: ...so that the type `T` will meet its required lifetime bounds
  --> src/main.rs:50:17
   |
50 |         Consumer(form.into_inner())
   |                       ^^^^^^^^^^

into_inner method on Form 要求它的类型参数 T 具有 'static 生命周期,并且错误消息建议添加此约束。

通过这些更改,它将编译:

impl<'f, T: 'static> Consumer<T> where T: FromForm<'f> {
    fn new(form: Form<'f, T>) -> Self {
        Consumer(form.into_inner())
    }

    fn get(&self) -> &T {
        &self.0
    }
}

【讨论】:

  • 太棒了,谢谢!!我仍在尝试了解 Rust 的生命周期。你知道为什么 Form.into_inner() 需要 'static on T 吗?
  • @TechieSprout 我对 Rocket 不是很熟悉,所以很难说。当你看得更深时,这可能是绝对有意义的。它也有可能作为 Rust 类型系统中某些缺陷的解决方法——可能存在也可能不存在。通过他们的official channels 之一可能值得询问
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-22
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
  • 2022-01-22
  • 2015-08-05
相关资源
最近更新 更多