Yay! Static fields, finally, minimally resolving [skip ci]

This commit is contained in:
tyranron 2022-09-20 18:06:07 +03:00
parent 0b6544db48
commit 2d01486ee9
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
3 changed files with 34 additions and 19 deletions

View file

@ -141,7 +141,7 @@ impl<'a, S: ScalarValue + 'a> SchemaType<'a, S> {
self.description.as_deref()
}
fn types(&self) -> Vec<TypeType<S>> {
fn types(&self) -> Vec<TypeType<'_, S>> {
self.type_list()
.into_iter()
.filter(|t| {
@ -156,21 +156,21 @@ impl<'a, S: ScalarValue + 'a> SchemaType<'a, S> {
}
#[graphql(name = "queryType")]
fn query_type_(&self) -> TypeType<S> {
fn query_type_(&self) -> TypeType<'_, S> {
self.query_type()
}
#[graphql(name = "mutationType")]
fn mutation_type_(&self) -> Option<TypeType<S>> {
fn mutation_type_(&self) -> Option<TypeType<'_, S>> {
self.mutation_type()
}
#[graphql(name = "subscriptionType")]
fn subscription_type_(&self) -> Option<TypeType<S>> {
fn subscription_type_(&self) -> Option<TypeType<'_, S>> {
self.subscription_type()
}
fn directives(&self) -> Vec<&DirectiveType<S>> {
fn directives(&self) -> Vec<&DirectiveType<'_, S>> {
self.directive_list()
}
}
@ -214,7 +214,7 @@ impl<'a, S: ScalarValue + 'a> TypeType<'a, S> {
fn fields(
&self,
#[graphql(default = false)] include_deprecated: Option<bool>,
) -> Option<Vec<&Field<S>>> {
) -> Option<Vec<&Field<'_, S>>> {
match self {
TypeType::Concrete(&MetaType::Interface(InterfaceMeta { ref fields, .. }))
| TypeType::Concrete(&MetaType::Object(ObjectMeta { ref fields, .. })) => Some(
@ -231,14 +231,14 @@ impl<'a, S: ScalarValue + 'a> TypeType<'a, S> {
}
}
fn of_type(&self) -> Option<&TypeType<S>> {
fn of_type(&self) -> Option<&TypeType<'_, S>> {
match self {
TypeType::Concrete(_) => None,
TypeType::List(l, _) | TypeType::NonNull(l) => Some(&**l),
}
}
fn input_fields(&self) -> Option<&[Argument<S>]> {
fn input_fields(&self) -> Option<&[Argument<'_, S>]> {
match self {
TypeType::Concrete(&MetaType::InputObject(InputObjectMeta {
ref input_fields,
@ -343,7 +343,7 @@ impl<'a, S: ScalarValue + 'a> Field<'a, S> {
self.description.as_deref()
}
fn args(&self) -> Vec<&Argument<S>> {
fn args(&self) -> Vec<&Argument<'_, S>> {
self.arguments
.as_ref()
.map_or_else(Vec::new, |v| v.iter().collect())
@ -434,7 +434,7 @@ impl<'a, S: ScalarValue + 'a> DirectiveType<'a, S> {
self.is_repeatable
}
fn args(&self) -> &[Argument<S>] {
fn args(&self) -> &[Argument<'_, S>] {
&self.arguments
}

View file

@ -124,9 +124,16 @@ pub(crate) trait TypeExt {
/// inferring.
fn lifetimes_anonymized(&mut self);
/// Anonymizes all the lifetime parameters of this [`syn::Type`] (except
/// the `'static` ones), making it suitable for using in contexts with
/// inferring, and returns it as a new type, leaving the original one
/// unchanged.
fn to_anonymized_lifetimes(&self) -> syn::Type;
/// Lifts all the lifetimes of this [`syn::Type`] (even elided, but except
/// `'static`) to a `for<>` quantifier, preserving the type speciality as
/// much as possible.
/// much as possible, and returns it as a new type, leaving the original one
/// unchanged.
fn to_hrtb_lifetimes(&self) -> (Option<syn::BoundLifetimes>, syn::Type);
/// Returns the topmost [`syn::Ident`] of this [`syn::TypePath`], if any.
@ -233,6 +240,12 @@ impl TypeExt for syn::Type {
});
}
fn to_anonymized_lifetimes(&self) -> syn::Type {
let mut ty = self.clone();
ty.lifetimes_anonymized();
ty
}
fn to_hrtb_lifetimes(&self) -> (Option<syn::BoundLifetimes>, syn::Type) {
let mut ty = self.clone();
let mut lts = vec![];

View file

@ -21,7 +21,7 @@ use crate::common::{
behavior, field, filter_attrs, gen,
parse::{
attr::{err, OptionExt as _},
GenericsExt as _, ParseBufferExt as _, TypeExt,
GenericsExt as _, ParseBufferExt as _, TypeExt as _,
},
rename, scalar, Description, SpanContainer,
};
@ -626,15 +626,18 @@ impl<Operation: ?Sized + 'static> Definition<Operation> {
let (f_ident, f_ty) = (&field.ident, &field.ty);
let body = if !field.is_async {
let (f_for_ty, f_hrtb_ty) = f_ty.to_hrtb_lifetimes();
generics.make_where_clause().predicates.push(parse_quote! {
#f_ty: ::juniper::resolve::Resolvable<#sv, #f_bh>
#f_for_ty #f_hrtb_ty:
::juniper::resolve::Resolvable<#sv, #f_bh>
});
generics.make_where_clause().predicates.push(parse_quote! {
<#f_ty as ::juniper::resolve::Resolvable<#sv, #f_bh>>::Value:
#f_for_ty <#f_hrtb_ty as ::juniper::resolve::Resolvable<#sv, #f_bh>>::Value:
::juniper::resolve::Value<#inf, #cx, #sv, #f_bh>
});
let res = if field.is_method() {
let val = if field.is_method() {
let f_anon_ty = f_ty.to_anonymized_lifetimes();
let args = field
.arguments
.as_ref()
@ -666,23 +669,22 @@ impl<Operation: ?Sized + 'static> Definition<Operation> {
}
}
});
let rcv = field.has_receiver.then(|| {
quote! { self, }
});
quote! {
<#f_ty as ::juniper::resolve::Resolvable<#sv, #f_bh>>
<#f_anon_ty as ::juniper::resolve::Resolvable<#sv, #f_bh>>
::into_value(Self::#f_ident(#rcv #( #args ),*))?
}
} else {
quote! {
&self.#f_ident
self.#f_ident
}
};
quote! {
executor.resolve_value::<#f_bh, _, _>(#res, type_info)
executor.resolve_value::<#f_bh, _, _>(&#val, type_info)
}
} else {
quote! {