From 2d01486ee9e1e03de2bd93b953cf9d5a35099133 Mon Sep 17 00:00:00 2001 From: tyranron Date: Tue, 20 Sep 2022 18:06:07 +0300 Subject: [PATCH] Yay! Static fields, finally, minimally resolving [skip ci] --- juniper/src/schema/schema.rs | 20 ++++++++++---------- juniper_codegen/src/common/parse/mod.rs | 15 ++++++++++++++- juniper_codegen/src/graphql_object/mod.rs | 18 ++++++++++-------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/juniper/src/schema/schema.rs b/juniper/src/schema/schema.rs index 61822746..311bcab2 100644 --- a/juniper/src/schema/schema.rs +++ b/juniper/src/schema/schema.rs @@ -141,7 +141,7 @@ impl<'a, S: ScalarValue + 'a> SchemaType<'a, S> { self.description.as_deref() } - fn types(&self) -> Vec> { + fn types(&self) -> Vec> { 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 { + fn query_type_(&self) -> TypeType<'_, S> { self.query_type() } #[graphql(name = "mutationType")] - fn mutation_type_(&self) -> Option> { + fn mutation_type_(&self) -> Option> { self.mutation_type() } #[graphql(name = "subscriptionType")] - fn subscription_type_(&self) -> Option> { + fn subscription_type_(&self) -> Option> { self.subscription_type() } - fn directives(&self) -> Vec<&DirectiveType> { + 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, - ) -> Option>> { + ) -> Option>> { 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> { + 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]> { + 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> { + 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] { + fn args(&self) -> &[Argument<'_, S>] { &self.arguments } diff --git a/juniper_codegen/src/common/parse/mod.rs b/juniper_codegen/src/common/parse/mod.rs index 5789f6e3..ba4e8718 100644 --- a/juniper_codegen/src/common/parse/mod.rs +++ b/juniper_codegen/src/common/parse/mod.rs @@ -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::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::Type) { let mut ty = self.clone(); let mut lts = vec![]; diff --git a/juniper_codegen/src/graphql_object/mod.rs b/juniper_codegen/src/graphql_object/mod.rs index 496294b3..a0cef4cb 100644 --- a/juniper_codegen/src/graphql_object/mod.rs +++ b/juniper_codegen/src/graphql_object/mod.rs @@ -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 Definition { 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 Definition { } } }); - 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! {