diff --git a/examples/warp_async/src/main.rs b/examples/warp_async/src/main.rs index 6b53ff38..a7142d4e 100644 --- a/examples/warp_async/src/main.rs +++ b/examples/warp_async/src/main.rs @@ -2,8 +2,6 @@ //! This example demonstrates async/await usage with warp. //! NOTE: this uses tokio 0.1 , not the alpha tokio 0.2. -#![feature(async_closure)] - use juniper::{EmptyMutation, RootNode, FieldError}; use warp::{http::Response, Filter}; diff --git a/integration_tests/async_await/src/main.rs b/integration_tests/async_await/src/main.rs index eed72dff..feb68bca 100644 --- a/integration_tests/async_await/src/main.rs +++ b/integration_tests/async_await/src/main.rs @@ -1,5 +1,3 @@ -#![feature(async_closure)] - use juniper::{graphql_value, RootNode, Value}; #[derive(juniper::GraphQLEnum)] diff --git a/juniper/src/executor/mod.rs b/juniper/src/executor/mod.rs index 27300882..2fdcd4fd 100644 --- a/juniper/src/executor/mod.rs +++ b/juniper/src/executor/mod.rs @@ -828,121 +828,10 @@ where None => return Err(GraphQLError::UnknownOperationName), }; - let default_variable_values = op.item.variable_definitions.map(|defs| { - defs.item - .items - .iter() - .filter_map(|&(ref name, ref def)| { - def.default_value - .as_ref() - .map(|i| (name.item.to_owned(), i.item.clone())) - }) - .collect::>>() - }); - - let errors = RwLock::new(Vec::new()); - let value; - - { - let mut all_vars; - let mut final_vars = variables; - - if let Some(defaults) = default_variable_values { - all_vars = variables.clone(); - - for (name, value) in defaults { - all_vars.entry(name).or_insert(value); - } - - final_vars = &all_vars; - } - - let root_type = match op.item.operation_type { - OperationType::Query => root_node.schema.query_type(), - OperationType::Mutation => root_node - .schema - .mutation_type() - .expect("No mutation type found"), - }; - - let executor = Executor { - fragments: &fragments - .iter() - .map(|f| (f.item.name.item, &f.item)) - .collect(), - variables: final_vars, - current_selection_set: Some(&op.item.selection_set[..]), - parent_selection_set: None, - current_type: root_type, - schema: &root_node.schema, - context, - errors: &errors, - field_path: FieldPath::Root(op.start), - }; - - value = match op.item.operation_type { - OperationType::Query => { - executor - .resolve_into_value_async(&root_node.query_info, &root_node) - .await - } - OperationType::Mutation => { - executor - .resolve_into_value_async(&root_node.mutation_info, &root_node.mutation_type) - .await - } - }; + if op.item.operation_type == OperationType::Subscription { + return Err(GraphQLError::IsSubscription); } - let mut errors = errors.into_inner().unwrap(); - errors.sort(); - - Ok((value, errors)) -} - -#[cfg(feature = "async")] -pub async fn execute_validated_query_async<'a, QueryT, MutationT, CtxT, S>( - document: Document<'a, S>, - operation_name: Option<&str>, - root_node: &RootNode<'a, QueryT, MutationT, S>, - variables: &Variables, - context: &CtxT, -) -> Result<(Value, Vec>), GraphQLError<'a>> -where - S: ScalarValue + Send + Sync, - QueryT: crate::GraphQLTypeAsync + Send + Sync, - QueryT::TypeInfo: Send + Sync, - MutationT: crate::GraphQLTypeAsync + Send + Sync, - MutationT::TypeInfo: Send + Sync, - CtxT: Send + Sync, - for<'b> &'b S: ScalarRefValue<'b>, -{ - let mut fragments = vec![]; - let mut operation = None; - - for def in document { - match def { - Definition::Operation(op) => { - if operation_name.is_none() && operation.is_some() { - return Err(GraphQLError::MultipleOperationsProvided); - } - - let move_op = operation_name.is_none() - || op.item.name.as_ref().map(|s| s.item) == operation_name; - - if move_op { - operation = Some(op); - } - } - Definition::Fragment(f) => fragments.push(f), - }; - } - - let op = match operation { - Some(op) => op, - None => return Err(GraphQLError::UnknownOperationName), - }; - let default_variable_values = op.item.variable_definitions.map(|defs| { defs.item .items @@ -978,6 +867,7 @@ where .schema .mutation_type() .expect("No mutation type found"), + OperationType::Subscription => unreachable!(), }; let executor = Executor { @@ -1006,6 +896,7 @@ where .resolve_into_value_async(&root_node.mutation_info, &root_node.mutation_type) .await } + OperationType::Subscription => unreachable!(), }; } diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs index e76efcaf..2d553896 100644 --- a/juniper/src/lib.rs +++ b/juniper/src/lib.rs @@ -90,7 +90,6 @@ Juniper has not reached 1.0 yet, thus some API instability should be expected. */ #![doc(html_root_url = "https://docs.rs/juniper/0.14.0")] #![warn(missing_docs)] -#![cfg_attr(feature = "async", feature(async_closure))] #[doc(hidden)] pub extern crate serde; diff --git a/juniper_benchmarks/src/lib.rs b/juniper_benchmarks/src/lib.rs index 65c3b20a..4a79da2f 100644 --- a/juniper_benchmarks/src/lib.rs +++ b/juniper_benchmarks/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(async_closure)] - use juniper::{ object, DefaultScalarValue, ExecutionError, FieldError, GraphQLEnum, Value, Variables, }; diff --git a/juniper_codegen/src/derive_object.rs b/juniper_codegen/src/derive_object.rs index c6042aa7..f7a4110f 100644 --- a/juniper_codegen/src/derive_object.rs +++ b/juniper_codegen/src/derive_object.rs @@ -59,7 +59,8 @@ pub fn build_derive_object(ast: syn::DeriveInput, is_internal: bool) -> TokenStr description: field_attrs.description, deprecation: field_attrs.deprecation, resolver_code, - resolver_code_async: None, + is_type_inferred: true, + is_async: false, }) } }); diff --git a/juniper_codegen/src/impl_object.rs b/juniper_codegen/src/impl_object.rs index 992e3570..88822cc7 100644 --- a/juniper_codegen/src/impl_object.rs +++ b/juniper_codegen/src/impl_object.rs @@ -197,29 +197,10 @@ pub fn build_object(args: TokenStream, body: TokenStream, is_internal: bool) -> } let body = &method.block; - let return_ty = &method.sig.output; - - let (resolver_code, resolver_code_async) = if is_async { - ( - quote!(), - Some(quote!( - (async move || #return_ty { - #( #resolve_parts )* - #body - })() - )), - ) - } else { - ( - quote!( - (|| #return_ty { - #( #resolve_parts )* - #body - })() - ), - None, - ) - }; + let resolver_code = quote!( + #( #resolve_parts )* + #body + ); let ident = &method.sig.ident; let name = attrs @@ -233,7 +214,8 @@ pub fn build_object(args: TokenStream, body: TokenStream, is_internal: bool) -> description: attrs.description, deprecation: attrs.deprecation, resolver_code, - resolver_code_async, + is_type_inferred: false, + is_async, }); } _ => { diff --git a/juniper_codegen/src/util.rs b/juniper_codegen/src/util.rs index 3c3b7d6c..a0dae69e 100644 --- a/juniper_codegen/src/util.rs +++ b/juniper_codegen/src/util.rs @@ -597,14 +597,8 @@ pub struct GraphQLTypeDefinitionField { pub deprecation: Option, pub args: Vec, pub resolver_code: proc_macro2::TokenStream, - pub resolver_code_async: Option, -} - -impl GraphQLTypeDefinitionField { - #[inline] - fn is_async(&self) -> bool { - self.resolver_code_async.is_some() - } + pub is_type_inferred: bool, + pub is_async: bool, } /// Definition of a graphql type based on information extracted @@ -638,7 +632,7 @@ pub struct GraphQLTypeDefiniton { impl GraphQLTypeDefiniton { fn has_async_field(&self) -> bool { - self.fields.iter().any(|field| field.is_async()) + self.fields.iter().any(|field| field.is_async) } pub fn into_tokens(self, juniper_crate_name: &str) -> proc_macro2::TokenStream { @@ -711,7 +705,7 @@ impl GraphQLTypeDefiniton { let name = &field.name; let code = &field.resolver_code; - if field.is_async() { + if field.is_async { // TODO: better error message with field/type name. quote!( #name => { @@ -719,9 +713,15 @@ impl GraphQLTypeDefiniton { }, ) } else { + let _type = if field.is_type_inferred { + quote!() + } else { + let _type = &field._type; + quote!(: #_type) + }; quote!( #name => { - let res = { #code }; + let res #_type = { #code }; #juniper_crate_name::IntoResolvable::into( res, executor.context() @@ -810,74 +810,79 @@ impl GraphQLTypeDefiniton { #[cfg(feature = "async")] let resolve_field_async = { let resolve_matches_async = self.fields.iter().map(|field| { - let name = &field.name; + let name = &field.name; + let code = &field.resolver_code; + let _type = if field.is_type_inferred { + quote!() + } else { + let _type = &field._type; + quote!(: #_type) + }; - if let Some(code) = field.resolver_code_async.as_ref() { - quote!( - #name => { - let f = async move { - let res = { #code }.await; + if field.is_async { + quote!( + #name => { + let f = async move { + let res #_type = async move { #code }.await; - let inner_res = #juniper_crate_name::IntoResolvable::into( - res, - executor.context() - ); - match inner_res { - Ok(Some((ctx, r))) => { - let subexec = executor - .replaced_context(ctx); - subexec.resolve_with_ctx_async(&(), &r) - .await - }, - Ok(None) => Ok(#juniper_crate_name::Value::null()), - Err(e) => Err(e), - } - }; - future::FutureExt::boxed(f) - }, - ) - } else { - let code = &field.resolver_code; - - let inner = if !self.no_async { - quote!( - let f = async move { - match res2 { - Ok(Some((ctx, r))) => { - let sub = executor.replaced_context(ctx); - sub.resolve_with_ctx_async(&(), &r).await - }, - Ok(None) => Ok(#juniper_crate_name::Value::null()), - Err(e) => Err(e), - } - }; - future::FutureExt::boxed(f) - ) - } else { - quote!( - let v = match res2 { - Ok(Some((ctx, r))) => executor.replaced_context(ctx).resolve_with_ctx(&(), &r), - Ok(None) => Ok(#juniper_crate_name::Value::null()), - Err(e) => Err(e), - }; - future::FutureExt::boxed(future::ready(v)) - ) + let inner_res = #juniper_crate_name::IntoResolvable::into( + res, + executor.context() + ); + match inner_res { + Ok(Some((ctx, r))) => { + let subexec = executor + .replaced_context(ctx); + subexec.resolve_with_ctx_async(&(), &r) + .await + }, + Ok(None) => Ok(#juniper_crate_name::Value::null()), + Err(e) => Err(e), + } }; + future::FutureExt::boxed(f) + }, + ) + } else { + let inner = if !self.no_async { + quote!( + let f = async move { + match res2 { + Ok(Some((ctx, r))) => { + let sub = executor.replaced_context(ctx); + sub.resolve_with_ctx_async(&(), &r).await + }, + Ok(None) => Ok(#juniper_crate_name::Value::null()), + Err(e) => Err(e), + } + }; + future::FutureExt::boxed(f) + ) + } else { + quote!( + let v = match res2 { + Ok(Some((ctx, r))) => executor.replaced_context(ctx).resolve_with_ctx(&(), &r), + Ok(None) => Ok(#juniper_crate_name::Value::null()), + Err(e) => Err(e), + }; + future::FutureExt::boxed(future::ready(v)) + ) + }; - quote!( - #name => { - let res = { #code }; - let res2 = #juniper_crate_name::IntoResolvable::into( - res, - executor.context() - ); - #inner - }, - ) - } - }); + quote!( + #name => { + let res #_type = { #code }; + let res2 = #juniper_crate_name::IntoResolvable::into( + res, + executor.context() + ); + #inner + }, + ) + } + }); - let mut where_async = where_clause.cloned().unwrap_or_else(|| parse_quote!(where));; + let mut where_async = where_clause.cloned().unwrap_or_else(|| parse_quote!(where)); where_async .predicates diff --git a/juniper_rocket/src/lib.rs b/juniper_rocket/src/lib.rs index 68817cb1..dd57769a 100644 --- a/juniper_rocket/src/lib.rs +++ b/juniper_rocket/src/lib.rs @@ -38,7 +38,6 @@ Check the LICENSE file for details. #![doc(html_root_url = "https://docs.rs/juniper_rocket/0.2.0")] #![feature(decl_macro, proc_macro_hygiene)] -#![cfg_attr(feature = "async", feature(async_closure))] use std::{error::Error, io::Cursor}; diff --git a/juniper_warp/src/lib.rs b/juniper_warp/src/lib.rs index b00a9b6c..55d423fd 100644 --- a/juniper_warp/src/lib.rs +++ b/juniper_warp/src/lib.rs @@ -39,7 +39,6 @@ Check the LICENSE file for details. #![deny(missing_docs)] #![deny(warnings)] #![doc(html_root_url = "https://docs.rs/juniper_warp/0.2.0")] -#![cfg_attr(feature = "async", feature(async_closure))] use futures::{future::poll_fn, Future}; use serde::Deserialize;