编译器告诉我添加一个明确的生命周期界限,但我不知道我应该怎么做。
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)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
这是我想出的重现错误的最少代码。它在ReturnType1不通用的时候工作V,E但我现在试图使它适用于多种类型:
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() {}
Run Code Online (Sandbox Code Playgroud)
货物.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" }
Run Code Online (Sandbox Code Playgroud)
困扰我的是泛型类型是在impl块上声明的,但问题似乎出在fn内部,因此在 impl 级别添加生命周期似乎是错误的方法。
如果我尝试在 上添加一个where S: 'a, E: 'a子句fn resolve():
[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" }
Run Code Online (Sandbox Code Playgroud)
它说该方法与特征声明不匹配:
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
Run Code Online (Sandbox Code Playgroud)
但我不能将它添加到特征中,因为它不知道S& E...
您可以在此 PR 中看到我尝试进行的更改:https : //github.com/mathroc/pgql-rs/pull/1/files
因此,awaitinto_graphql可能会在 - 的生命周期中的任何时间解析f- 当发生这种情况时,随后的into()调用显然需要相应类型中的数据有效。Ergo,to_graphql的类型参数V并且E必须比它的生命周期参数存活时间长'a。借用检查器隐式地强制执行此操作,如asyncLifetimes下所述:
与传统函数不同
async fn,采用引用或其他非'static参数的s返回Future受参数生命周期限制的a :
您想指定您的实现块的泛型类型参数S并E具有这样的生命周期,但正如您所指出的,当它没有出现在特征定义中时,您不能添加这样的约束。
一种可能性是向Registrable特征本身添加一个生命周期参数,并在resolve函数上指定这个新的特征生命周期参数是(即超过)函数生命周期参数的子类型'a:
trait Registrable<'b>: Send + Sync
{
fn resolve<'a>(
&self,
executor: &'a juniper::Executor<Context, juniper::DefaultScalarValue>,
) -> ReturnType<'a>
where 'b: 'a;
}
Run Code Online (Sandbox Code Playgroud)
然后,您impl可以将该生命周期参数与泛型类型参数相关联,S并且E:
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)))
}
}
Run Code Online (Sandbox Code Playgroud)