rust - 我应该在哪里添加明确的生命周期界限?

标签 rust

编译器告诉我要添加一个明确的生命周期界限,但我不知道我应该怎么做。

    error[E0309]: the parameter type `E` may not live long enough
      --> src/main.rs:39:9
       |
    34 | impl<S: Into<juniper::Value>, E: Into<juniper::FieldError>> Registrable for FieldInfo<S,E>
       |                               -- help: consider adding an explicit lifetime bound...: `E: 'a +`
    ...
    39 |         Box::pin(to_graphql((self.resolver)(executor)))
       |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |
    note: ...so that the type `impl std::future::Future` will meet its required lifetime bounds
      --> src/main.rs:39:9
       |
    39 |         Box::pin(to_graphql((self.resolver)(executor)))
       |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
server_1
    error[E0309]: the parameter type `S` may not live long enough
      --> src/main.rs:39:9
       |
    34 | impl<S: Into<juniper::Value>, E: Into<juniper::FieldError>> Registrable for FieldInfo<S,E>
       |      -- help: consider adding an explicit lifetime bound...: `S: 'a +`
    ...
    39 |         Box::pin(to_graphql((self.resolver)(executor)))
       |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |
    note: ...so that the type `impl std::future::Future` will meet its required lifetime bounds
      --> src/main.rs:39:9
       |
    39 |         Box::pin(to_graphql((self.resolver)(executor)))
       |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

这是我想出的重现错误的最少代码。当 ReturnType1 时它正在工作不是通用的 VE但我现在正在尝试使其适用于多种类型:

use juniper;

#[derive(Clone)]
struct Context {}

impl juniper::Context for Context {}

type ReturnType1<'a, V: Into<juniper::Value>, E: Into<juniper::FieldError>> = juniper::BoxFuture<'a, Result<V,E>>;
type InnerReturnType = juniper::ExecutionResult<juniper::DefaultScalarValue>;
type ReturnType<'a> = juniper::BoxFuture<'a, InnerReturnType>;

type Resolver<V: Into<juniper::Value>, E: Into<juniper::FieldError>> = for<'a> fn(
    &'a juniper::Executor<Context, juniper::DefaultScalarValue>
) -> ReturnType1<'a, V, E>;

async fn to_graphql<'a, V: Into<juniper::Value>, E: Into<juniper::FieldError>>(f: ReturnType1<'a, V, E>) -> InnerReturnType {
    f.await
        .map(|scalar| scalar.into())
        .map_err(|err| err.into())
}

trait Registrable: Send + Sync
{
    fn resolve<'a>(self: &Self, executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>) -> ReturnType<'a>;
}

struct FieldInfo<S, E>
where S: Into<juniper::Value>,
    E: Into<juniper::FieldError>
{
    resolver: Resolver<S,E>
}

impl<S: Into<juniper::Value>, E: Into<juniper::FieldError>> Registrable for FieldInfo<S,E>
where S: juniper::GraphQLType<TypeInfo=()> + Send + Sync
{
    fn resolve<'a>(self: &Self, executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>) -> ReturnType<'a>
    {
        Box::pin(to_graphql((self.resolver)(executor)))
    }
}

fn main() {}

cargo .toml:
[package]
name = "pgql"
version = "0.1.0"
authors = ["Mathieu Rochette <mathieu@texthtml.net>"]
edition = "2018"

[dependencies]
juniper = { git = "https://github.com/graphql-rust/juniper", branch = "master" }

困扰我的是泛型类型是在 impl 上声明的。阻止但问题似乎出在 fn 上在内部,因此在 impl 级别添加生命周期似乎是错误的方法。

如果我尝试添加 where S: 'a, E: 'a关于 fn resolve() 的条款:

impl<S: Into<juniper::Value>, E: Into<juniper::FieldError>> Registrable for FieldInfo<S,E>
where S: juniper::GraphQLType<TypeInfo=()> + Send + Sync
{
    fn resolve<'a>(self: &Self, executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>) -> ReturnType<'a>
    where S: 'a, E: 'a {
        Box::pin(to_graphql((self.resolver)(executor)))
    }
}

它说该方法与特征声明不匹配:
error[E0195]: lifetime parameters or bounds on method `resolve` do not match the trait declaration
  --> src/main.rs:37:15
   |
24 |     fn resolve<'a>(self: &Self, executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>) -> ReturnType<'a>;
   |               ---- lifetimes in impl do not match this method in trait
...
37 |     fn resolve<'a>(self: &Self, executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>) -> ReturnType<'a>
   |               ^^^^ lifetimes do not match method in trait

但我不能将它添加到特征中,因为它不知道 S & E ...

你可以看到我试图在这个 PR 中做出的改变:https://github.com/mathroc/pgql-rs/pull/1/files

最佳答案

所以,awaitto_graphql可能会在 f 的生命周期内的任何时间解决- 当这种情况发生时,随后的 into()调用显然需要相应类型的数据有效。因此,to_graphql的类型参数 VE必须超过其生命周期参数 'a .如 async Lifetimes 中所述,借用检查器会隐式强制执行此操作。 :

Unlike traditional functions, async fns which take references or other non-'static arguments return a Future which is bounded by the lifetime of the arguments:



您想指定实现块的泛型类型参数 SE有这样的生命周期,但正如您所指出的,当它没有出现在特征定义中时,您不能添加这样的约束。

一种可能性是向 Registrable 添加生命周期参数。 trait 本身,以及 resolve函数指定这个新的特征生命周期参数是函数生命周期参数 'a 的子类型(即生命周期更长) :
trait Registrable<'b>: Send + Sync
{
    fn resolve<'a>(
        &self,
        executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>,
    ) -> ReturnType<'a>
    where 'b: 'a;
}

然后在您的 impl您可以将该生命周期参数与泛型类型参数相关联 SE :
impl<'b, S, E> Registrable<'b> for FieldInfo<S, E>
where
    S: juniper::GraphQLType<TypeInfo=()>,
    S: Send,
    S: Sync,
    S: Into<juniper::Value>,
    E: Into<juniper::FieldError>,
    S: 'b,
    E: 'b,
{
    fn resolve<'a>(
        &self,
        executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>,
    ) -> ReturnType<'a>
    where 'b: 'a
    {
        Box::pin(to_graphql((self.resolver)(executor)))
    }
}

关于rust - 我应该在哪里添加明确的生命周期界限?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61638478/

相关文章:

rust - 轮询许多不同类型的 future

rust - 如何在 Rust 中同时分配 2 个变量?

c++ - 将 Cpp 转换为 Rust,处理全局静态对象

rust - 如何制作其中一个字段引用另一个字段的结构

rust - 当片段大小可以在每次迭代中更改时,在循环中消耗切片片段的正确方法是什么?

rust - 使用未初始化的数据将 `Rc<RefCell<MaybeUninit<T>>` 克隆为 `Rc<RefCell<T>` 是否安全?

rust - 如何在 rust-fuse 中找到路径?

rust - 在闭包中通过引用保存一个值

rust - 如何使用 tokio 的 UdpSocket 处理 1 台服务器中的消息 : N clients setup?

rust - 如何构建在WSL上使用device_query crate 的项目?