diff --git a/benches/src/lib.rs b/benches/src/lib.rs index ef284cc7d..9b2875885 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -95,8 +95,7 @@ impl Query { } } -pub fn new_schema() -> RootNode<'static, Query, EmptyMutation, EmptySubscription> -{ +pub fn new_schema() -> RootNode, EmptySubscription> { RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new()) } diff --git a/book/src/quickstart.md b/book/src/quickstart.md index ff6cf3da0..65b45bc35 100644 --- a/book/src/quickstart.md +++ b/book/src/quickstart.md @@ -140,7 +140,7 @@ impl Mutation { // Root schema consists of a query, a mutation, and a subscription. // Request queries can be executed against a `RootNode`. -type Schema = juniper::RootNode<'static, Query, Mutation, EmptySubscription>; +type Schema = juniper::RootNode>; # # fn main() { # _ = Schema::new(Query, Mutation, EmptySubscription::new()); @@ -190,7 +190,7 @@ impl Query { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode, EmptySubscription>; fn main() { // Create a context. diff --git a/book/src/schema/index.md b/book/src/schema/index.md index ab801c7c7..a46ed32cf 100644 --- a/book/src/schema/index.md +++ b/book/src/schema/index.md @@ -52,7 +52,7 @@ impl Mutation { } } -type Schema = RootNode<'static, Query, Mutation, EmptySubscription>; +type Schema = RootNode; # # fn main() {} ``` @@ -138,7 +138,7 @@ impl Query { } } -type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = RootNode; fn main() { // Run the built-in introspection query. diff --git a/book/src/schema/introspection.md b/book/src/schema/introspection.md index e5d222180..05ea42f1c 100644 --- a/book/src/schema/introspection.md +++ b/book/src/schema/introspection.md @@ -45,7 +45,7 @@ impl Query { } } -type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = RootNode; fn main() { let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()) diff --git a/book/src/schema/subscriptions.md b/book/src/schema/subscriptions.md index b4bf78a94..38f5f23c2 100644 --- a/book/src/schema/subscriptions.md +++ b/book/src/schema/subscriptions.md @@ -113,7 +113,7 @@ While we can implement [`SubscriptionCoordinator`] ourselves, [Juniper] contains # } # } # -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode, Subscription>; fn schema() -> Schema { Schema::new(Query, EmptyMutation::new(), Subscription) diff --git a/juniper/CHANGELOG.md b/juniper/CHANGELOG.md index 6bf096d4d..bc6a133a1 100644 --- a/juniper/CHANGELOG.md +++ b/juniper/CHANGELOG.md @@ -31,6 +31,39 @@ All user visible changes to `juniper` crate will be documented in this file. Thi - `uuid::Uuid`. - Renamed `ObjectId` scalar to `ObjectID` in types: ([#1277]) - `bson::oid::ObjectId`. +- Optimized schema implementation with [`arcstr` crate]: ([#1247], [#819]) + - `ast::Type`: + - Removed lifetime parameters. + - Made it generic over string type. + - `MetaType`: + - Removed lifetime parameters. + - Made `name()`, `description()` and `specified_by_url()` methods returning `ArcStr`. + - `EnumMeta`, `InputObjectMeta`, `InterfaceMeta`, `ListMeta`, `NullableMeta`, `ObjectMeta`, `PlaceholderMeta`, `ScalarMeta` and `UnionMeta`: + - Removed lifetime parameters. + - `meta::Field` and `meta::Argument`: + - Removed lifetime parameters. + - `meta::EnumValue`: + - Made `name` and `description` fields using `ArcStr`. + - `DeprecationStatus`: + - Made `Deprecated` variant using `ArcStr`. + - Made `reason()` method returning `ArcStr`. + - `DirectiveType`: + - Removed lifetime parameters. + - Made `name` and `description` fields using `ArcStr`. + - `SchemaType`: + - Removed lifetime parameters. + - Made `is_subtype()` method accepting `DynType` instead of `Type`. + - `RootNode`: + - Removed lifetime parameters. + - `Registry`: + - Removed lifetime parameters. + - `types::Name` and `types::NameParseError`: + - Made fields using `ArcStr` instead of `String`. + - Replaced `FromStr` impl of `types::Name` with `new()` constructor. + - `GraphQLType`: + - Made `name()` method returning `ArcStr`. + - `GraphQLValue`: + - Made `type_name()` method returning `ArcStr`. ### Added @@ -53,6 +86,8 @@ All user visible changes to `juniper` crate will be documented in this file. Thi - Incorrect error propagation inside fragments. ([#1318], [#1287]) +[#819]: /../../issues/819 +[#1247]: /../../pull/1247 [#1252]: /../../pull/1252 [#1270]: /../../issues/1270 [#1271]: /../../pull/1271 @@ -264,6 +299,7 @@ See [old CHANGELOG](/../../blob/juniper-v0.15.12/juniper/CHANGELOG.md). [`anyhow` crate]: https://docs.rs/anyhow +[`arcstr` crate]: https://docs.rs/arcstr [`bigdecimal` crate]: https://docs.rs/bigdecimal [`bson` crate]: https://docs.rs/bson [`chrono` crate]: https://docs.rs/chrono diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index 0e58cfc43..e3f4cfb41 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -43,6 +43,7 @@ uuid = ["dep:uuid"] [dependencies] anyhow = { version = "1.0.47", optional = true } +arcstr = { version = "1.1", default-features = false } async-trait = "0.1.39" auto_enums = "0.8" bigdecimal = { version = "0.4", optional = true } diff --git a/juniper/src/ast.rs b/juniper/src/ast.rs index 4d332d5ad..a7ee27ef2 100644 --- a/juniper/src/ast.rs +++ b/juniper/src/ast.rs @@ -1,5 +1,7 @@ use std::{borrow::Cow, fmt, hash::Hash, slice, vec}; +use arcstr::ArcStr; + use indexmap::IndexMap; use crate::{ @@ -8,24 +10,70 @@ use crate::{ value::{DefaultScalarValue, ScalarValue}, }; -/// A type literal in the syntax tree +/// Type literal in a syntax tree. /// -/// This enum carries no semantic information and might refer to types that do -/// not exist. -#[derive(Clone, Eq, PartialEq, Debug)] -pub enum Type<'a> { - /// A nullable named type, e.g. `String` - Named(Cow<'a, str>), - /// A nullable list type, e.g. `[String]` +/// This enum carries no semantic information and might refer to types that do not exist. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Type { + /// `null`able named type, e.g. `String`. + Named(N), + + /// `null`able list type, e.g. `[String]`. /// - /// The list itself is what's nullable, the containing type might be non-null. - List(Box>, Option), - /// A non-null named type, e.g. `String!` - NonNullNamed(Cow<'a, str>), - /// A non-null list type, e.g. `[String]!`. + /// The list itself is `null`able, the containing [`Type`] might be non-`null`. + List(Box>, Option), + + /// Non-`null` named type, e.g. `String!`. + NonNullNamed(N), + + /// Non-`null` list type, e.g. `[String]!`. /// - /// The list itself is what's non-null, the containing type might be null. - NonNullList(Box>, Option), + /// The list itself is non-`null`, the containing [`Type`] might be `null`able. + NonNullList(Box>, Option), +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Named(n) => write!(f, "{n}"), + Self::NonNullNamed(n) => write!(f, "{n}!"), + Self::List(t, _) => write!(f, "[{t}]"), + Self::NonNullList(t, _) => write!(f, "[{t}]!"), + } + } +} + +impl> Type { + /// Returns the name of this named [`Type`]. + /// + /// Only applies to named [`Type`]s. Lists will return [`None`]. + #[must_use] + pub fn name(&self) -> Option<&str> { + match self { + Self::Named(n) | Self::NonNullNamed(n) => Some(n.as_ref()), + Self::List(..) | Self::NonNullList(..) => None, + } + } + + /// Returns the innermost name of this [`Type`] by unpacking lists. + /// + /// All [`Type`] literals contain exactly one named type. + #[must_use] + pub fn innermost_name(&self) -> &str { + match self { + Self::Named(n) | Self::NonNullNamed(n) => n.as_ref(), + Self::List(l, ..) | Self::NonNullList(l, ..) => l.innermost_name(), + } + } + + /// Indicates whether this [`Type`] can only represent non-`null` values. + #[must_use] + pub fn is_non_null(&self) -> bool { + match self { + Self::NonNullList(..) | Self::NonNullNamed(..) => true, + Self::List(..) | Self::Named(..) => false, + } + } } /// A JSON-like value that can be passed into the query execution, either @@ -34,8 +82,8 @@ pub enum Type<'a> { /// /// Lists and objects variants are _spanned_, i.e. they contain a reference to /// their position in the source file, if available. -#[derive(Clone, Debug, PartialEq)] #[expect(missing_docs, reason = "self-explanatory")] +#[derive(Clone, Debug, PartialEq)] pub enum InputValue { Null, Scalar(S), @@ -45,24 +93,24 @@ pub enum InputValue { Object(Vec<(Spanning, Spanning>)>), } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct VariableDefinition<'a, S> { - pub var_type: Spanning>, + pub var_type: Spanning>, pub default_value: Option>>, pub directives: Option>>>, } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Arguments<'a, S> { pub items: Vec<(Spanning<&'a str>, Spanning>)>, } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct VariableDefinitions<'a, S> { pub items: Vec<(Spanning<&'a str>, VariableDefinition<'a, S>)>, } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Field<'a, S> { pub alias: Option>, pub name: Spanning<&'a str>, @@ -71,13 +119,13 @@ pub struct Field<'a, S> { pub selection_set: Option>>, } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct FragmentSpread<'a, S> { pub name: Spanning<&'a str>, pub directives: Option>>>, } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct InlineFragment<'a, S> { pub type_condition: Option>, pub directives: Option>>>, @@ -99,15 +147,15 @@ pub struct InlineFragment<'a, S> { /// } /// } /// ``` -#[derive(Clone, PartialEq, Debug)] #[expect(missing_docs, reason = "self-explanatory")] +#[derive(Clone, Debug, PartialEq)] pub enum Selection<'a, S = DefaultScalarValue> { Field(Spanning>), FragmentSpread(Spanning>), InlineFragment(Spanning>), } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Directive<'a, S> { pub name: Spanning<&'a str>, pub arguments: Option>>, @@ -122,7 +170,7 @@ pub enum OperationType { } #[expect(missing_docs, reason = "self-explanatory")] -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Operation<'a, S> { pub operation_type: OperationType, pub name: Option>, @@ -131,7 +179,7 @@ pub struct Operation<'a, S> { pub selection_set: Vec>, } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Fragment<'a, S> { pub name: Spanning<&'a str>, pub type_condition: Spanning<&'a str>, @@ -140,7 +188,7 @@ pub struct Fragment<'a, S> { } #[doc(hidden)] -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum Definition<'a, S> { Operation(Spanning>), Fragment(Spanning>), @@ -194,44 +242,6 @@ pub trait ToInputValue: Sized { fn to_input_value(&self) -> InputValue; } -impl Type<'_> { - /// Get the name of a named type. - /// - /// Only applies to named types; lists will return `None`. - pub fn name(&self) -> Option<&str> { - match *self { - Type::Named(ref n) | Type::NonNullNamed(ref n) => Some(n), - _ => None, - } - } - - /// Get the innermost name by unpacking lists - /// - /// All type literals contain exactly one named type. - pub fn innermost_name(&self) -> &str { - match *self { - Type::Named(ref n) | Type::NonNullNamed(ref n) => n, - Type::List(ref l, _) | Type::NonNullList(ref l, _) => l.innermost_name(), - } - } - - /// Determines if a type only can represent non-null values. - pub fn is_non_null(&self) -> bool { - matches!(*self, Type::NonNullNamed(_) | Type::NonNullList(..)) - } -} - -impl fmt::Display for Type<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Named(n) => write!(f, "{n}"), - Self::NonNullNamed(n) => write!(f, "{n}!"), - Self::List(t, _) => write!(f, "[{t}]"), - Self::NonNullList(t, _) => write!(f, "[{t}]!"), - } - } -} - impl InputValue { /// Construct a `null` value. pub fn null() -> Self { @@ -574,7 +584,7 @@ impl<'a, S> Arguments<'a, S> { } impl<'a, S> VariableDefinitions<'a, S> { - pub fn iter(&self) -> slice::Iter<(Spanning<&'a str>, VariableDefinition)> { + pub fn iter(&self) -> slice::Iter<(Spanning<&'a str>, VariableDefinition<'a, S>)> { self.items.iter() } } diff --git a/juniper/src/executor/mod.rs b/juniper/src/executor/mod.rs index 5b178f550..cc02440a3 100644 --- a/juniper/src/executor/mod.rs +++ b/juniper/src/executor/mod.rs @@ -8,6 +8,7 @@ use std::{ sync::{Arc, RwLock}, }; +use arcstr::ArcStr; use fnv::FnvHashMap; use futures::Stream; @@ -46,16 +47,6 @@ pub use self::{ mod look_ahead; mod owned_executor; -/// A type registry used to build schemas -/// -/// The registry gathers metadata for all types in a schema. It provides -/// convenience methods to convert types implementing the `GraphQLType` trait -/// into `Type` instances and automatically registers them. -pub struct Registry<'r, S = DefaultScalarValue> { - /// Currently registered types - pub types: FnvHashMap>, -} - #[expect(missing_docs, reason = "self-explanatory")] #[derive(Clone)] pub enum FieldPath<'a> { @@ -77,7 +68,7 @@ where current_selection_set: Option<&'r [Selection<'a, S>]>, parent_selection_set: Option<&'r [Selection<'a, S>]>, current_type: TypeType<'a, S>, - schema: &'a SchemaType<'a, S>, + schema: &'a SchemaType, context: &'a CtxT, errors: &'r RwLock>>, field_path: Arc>, @@ -893,10 +884,10 @@ where /// Create new `Executor` and start asynchronous query execution. /// Returns `IsSubscription` error if subscription is passed. -pub async fn execute_validated_query_async<'a, 'b, QueryT, MutationT, SubscriptionT, S>( - document: &'b Document<'a, S>, +pub async fn execute_validated_query_async<'b, QueryT, MutationT, SubscriptionT, S>( + document: &'b Document<'_, S>, operation: &'b Spanning>, - root_node: &RootNode<'a, QueryT, MutationT, SubscriptionT, S>, + root_node: &RootNode, variables: &Variables, context: &QueryT::Context, ) -> Result<(Value, Vec>), GraphQLError> @@ -1040,7 +1031,7 @@ pub async fn resolve_validated_subscription< >( document: &Document<'d, S>, operation: &Spanning>, - root_node: &'r RootNode<'r, QueryT, MutationT, SubscriptionT, S>, + root_node: &'r RootNode, variables: &Variables, context: &'r QueryT::Context, ) -> Result<(Value>, Vec>), GraphQLError> @@ -1136,46 +1127,52 @@ where Ok((value, errors)) } -impl<'r, S: 'r> Registry<'r, S> { +/// A type registry used to build schemas +/// +/// The registry gathers metadata for all types in a schema. It provides +/// convenience methods to convert types implementing the `GraphQLType` trait +/// into `Type` instances and automatically registers them. +pub struct Registry { + /// Currently registered types + pub types: FnvHashMap>, +} + +impl Registry { /// Constructs a new [`Registry`] out of the given `types`. - pub fn new(types: FnvHashMap>) -> Self { + pub fn new(types: FnvHashMap>) -> Self { Self { types } } - /// Returns a [`Type`] instance for the given [`GraphQLType`], registered in - /// this [`Registry`]. + /// Returns a [`Type`] instance for the given [`GraphQLType`], registered in this [`Registry`]. /// - /// If this [`Registry`] hasn't seen a [`Type`] with such - /// [`GraphQLType::name`] before, it will construct the one and store it. - pub fn get_type(&mut self, info: &T::TypeInfo) -> Type<'r> + /// If this [`Registry`] hasn't seen a [`Type`] with such [`GraphQLType::name`] before, it will + /// construct the one and store it. + pub fn get_type(&mut self, info: &T::TypeInfo) -> Type where T: GraphQLType + ?Sized, S: ScalarValue, { if let Some(name) = T::name(info) { - let validated_name = name.parse::().unwrap(); - if !self.types.contains_key(name) { - self.insert_placeholder( - validated_name.clone(), - Type::NonNullNamed(Cow::Owned(name.into())), - ); + let validated_name = Name::new(name.clone()).unwrap(); + if !self.types.contains_key(&name) { + self.insert_placeholder(validated_name.clone(), Type::NonNullNamed(name.clone())); let meta = T::meta(info, self); self.types.insert(validated_name, meta); } - self.types[name].as_type() + self.types[&name].as_type() } else { T::meta(info, self).as_type() } } /// Creates a [`Field`] with the provided `name`. - pub fn field(&mut self, name: &str, info: &T::TypeInfo) -> Field<'r, S> + pub fn field(&mut self, name: impl Into, info: &T::TypeInfo) -> Field where T: GraphQLType + ?Sized, S: ScalarValue, { Field { - name: smartstring::SmartString::from(name), + name: name.into(), description: None, arguments: None, field_type: self.get_type::(info), @@ -1186,9 +1183,9 @@ impl<'r, S: 'r> Registry<'r, S> { #[doc(hidden)] pub fn field_convert<'a, T: IntoResolvable<'a, S, I, C>, I, C>( &mut self, - name: &str, + name: impl Into, info: &I::TypeInfo, - ) -> Field<'r, S> + ) -> Field where I: GraphQLType, S: ScalarValue, @@ -1203,7 +1200,7 @@ impl<'r, S: 'r> Registry<'r, S> { } /// Creates an [`Argument`] with the provided `name`. - pub fn arg(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S> + pub fn arg(&mut self, name: impl Into, info: &T::TypeInfo) -> Argument where T: GraphQLType + FromInputValue, S: ScalarValue, @@ -1214,10 +1211,10 @@ impl<'r, S: 'r> Registry<'r, S> { /// Creates an [`Argument`] with the provided default `value`. pub fn arg_with_default( &mut self, - name: &str, + name: impl Into, value: &T, info: &T::TypeInfo, - ) -> Argument<'r, S> + ) -> Argument where T: GraphQLType + ToInputValue + FromInputValue, S: ScalarValue, @@ -1225,14 +1222,14 @@ impl<'r, S: 'r> Registry<'r, S> { Argument::new(name, self.get_type::(info)).default_value(value.to_input_value()) } - fn insert_placeholder(&mut self, name: Name, of_type: Type<'r>) { + fn insert_placeholder(&mut self, name: Name, of_type: Type) { self.types .entry(name) .or_insert(MetaType::Placeholder(PlaceholderMeta { of_type })); } /// Creates a [`ScalarMeta`] type. - pub fn build_scalar_type(&mut self, info: &T::TypeInfo) -> ScalarMeta<'r, S> + pub fn build_scalar_type(&mut self, info: &T::TypeInfo) -> ScalarMeta where T: GraphQLType + FromInputValue + ParseScalarValue, T::Error: IntoFieldError, @@ -1240,7 +1237,7 @@ impl<'r, S: 'r> Registry<'r, S> { { let name = T::name(info).expect("Scalar types must be named. Implement `name()`"); - ScalarMeta::new::(Cow::Owned(name.into())) + ScalarMeta::new::(name) } /// Creates a [`ListMeta`] type. @@ -1251,7 +1248,7 @@ impl<'r, S: 'r> Registry<'r, S> { &mut self, info: &T::TypeInfo, expected_size: Option, - ) -> ListMeta<'r> + ) -> ListMeta where T: GraphQLType + ?Sized, S: ScalarValue, @@ -1261,7 +1258,7 @@ impl<'r, S: 'r> Registry<'r, S> { } /// Creates a [`NullableMeta`] type. - pub fn build_nullable_type(&mut self, info: &T::TypeInfo) -> NullableMeta<'r> + pub fn build_nullable_type(&mut self, info: &T::TypeInfo) -> NullableMeta where T: GraphQLType + ?Sized, S: ScalarValue, @@ -1271,11 +1268,7 @@ impl<'r, S: 'r> Registry<'r, S> { } /// Creates an [`ObjectMeta`] type with the given `fields`. - pub fn build_object_type( - &mut self, - info: &T::TypeInfo, - fields: &[Field<'r, S>], - ) -> ObjectMeta<'r, S> + pub fn build_object_type(&mut self, info: &T::TypeInfo, fields: &[Field]) -> ObjectMeta where T: GraphQLType + ?Sized, S: ScalarValue, @@ -1283,16 +1276,12 @@ impl<'r, S: 'r> Registry<'r, S> { let name = T::name(info).expect("Object types must be named. Implement name()"); let mut v = fields.to_vec(); - v.push(self.field::("__typename", &())); - ObjectMeta::new(Cow::Owned(name.into()), &v) + v.push(self.field::(arcstr::literal!("__typename"), &())); + ObjectMeta::new(name, &v) } /// Creates an [`EnumMeta`] type out of the provided `values`. - pub fn build_enum_type( - &mut self, - info: &T::TypeInfo, - values: &[EnumValue], - ) -> EnumMeta<'r, S> + pub fn build_enum_type(&mut self, info: &T::TypeInfo, values: &[EnumValue]) -> EnumMeta where T: GraphQLType + FromInputValue, T::Error: IntoFieldError, @@ -1300,15 +1289,15 @@ impl<'r, S: 'r> Registry<'r, S> { { let name = T::name(info).expect("Enum types must be named. Implement `name()`"); - EnumMeta::new::(Cow::Owned(name.into()), values) + EnumMeta::new::(name, values) } /// Creates an [`InterfaceMeta`] type with the given `fields`. pub fn build_interface_type( &mut self, info: &T::TypeInfo, - fields: &[Field<'r, S>], - ) -> InterfaceMeta<'r, S> + fields: &[Field], + ) -> InterfaceMeta where T: GraphQLType + ?Sized, S: ScalarValue, @@ -1316,27 +1305,27 @@ impl<'r, S: 'r> Registry<'r, S> { let name = T::name(info).expect("Interface types must be named. Implement name()"); let mut v = fields.to_vec(); - v.push(self.field::("__typename", &())); - InterfaceMeta::new(Cow::Owned(name.into()), &v) + v.push(self.field::(arcstr::literal!("__typename"), &())); + InterfaceMeta::new(name, &v) } /// Creates an [`UnionMeta`] type of the given `types`. - pub fn build_union_type(&mut self, info: &T::TypeInfo, types: &[Type<'r>]) -> UnionMeta<'r> + pub fn build_union_type(&mut self, info: &T::TypeInfo, types: &[Type]) -> UnionMeta where T: GraphQLType + ?Sized, S: ScalarValue, { let name = T::name(info).expect("Union types must be named. Implement name()"); - UnionMeta::new(Cow::Owned(name.into()), types) + UnionMeta::new(name, types) } /// Creates an [`InputObjectMeta`] type with the given `args`. pub fn build_input_object_type( &mut self, info: &T::TypeInfo, - args: &[Argument<'r, S>], - ) -> InputObjectMeta<'r, S> + args: &[Argument], + ) -> InputObjectMeta where T: GraphQLType + FromInputValue, T::Error: IntoFieldError, @@ -1344,6 +1333,6 @@ impl<'r, S: 'r> Registry<'r, S> { { let name = T::name(info).expect("Input object types must be named. Implement name()"); - InputObjectMeta::new::(Cow::Owned(name.into()), args) + InputObjectMeta::new::(name, args) } } diff --git a/juniper/src/executor/owned_executor.rs b/juniper/src/executor/owned_executor.rs index e55514d3e..a4afb2ac2 100644 --- a/juniper/src/executor/owned_executor.rs +++ b/juniper/src/executor/owned_executor.rs @@ -19,7 +19,7 @@ pub struct OwnedExecutor<'a, CtxT, S> { pub(super) current_selection_set: Option>>, pub(super) parent_selection_set: Option>>, pub(super) current_type: TypeType<'a, S>, - pub(super) schema: &'a SchemaType<'a, S>, + pub(super) schema: &'a SchemaType, pub(super) context: &'a CtxT, pub(super) errors: RwLock>>, pub(super) field_path: Arc>, diff --git a/juniper/src/executor_tests/executor.rs b/juniper/src/executor_tests/executor.rs index 3c04e7398..a80a4db80 100644 --- a/juniper/src/executor_tests/executor.rs +++ b/juniper/src/executor_tests/executor.rs @@ -738,7 +738,7 @@ mod propagates_errors_to_nullable_fields { } } - fn schema() -> RootNode<'static, Schema, EmptyMutation, EmptySubscription> { + fn schema() -> RootNode { RootNode::new( Schema, EmptyMutation::<()>::new(), diff --git a/juniper/src/http/mod.rs b/juniper/src/http/mod.rs index 3e395169f..ad279c70f 100644 --- a/juniper/src/http/mod.rs +++ b/juniper/src/http/mod.rs @@ -109,7 +109,7 @@ where /// top level of this crate. pub async fn execute<'a, QueryT, MutationT, SubscriptionT>( &'a self, - root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>, + root_node: &'a RootNode, context: &'a QueryT::Context, ) -> GraphQLResponse where @@ -135,7 +135,7 @@ where /// level of this crate. pub async fn resolve_into_stream<'req, 'rn, 'ctx, 'a, QueryT, MutationT, SubscriptionT, S>( req: &'req GraphQLRequest, - root_node: &'rn RootNode<'a, QueryT, MutationT, SubscriptionT, S>, + root_node: &'rn RootNode, context: &'ctx QueryT::Context, ) -> Result<(Value>, Vec>), GraphQLError> where @@ -303,7 +303,7 @@ where /// GraphQLRequest pub async fn execute<'a, QueryT, MutationT, SubscriptionT>( &'a self, - root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>, + root_node: &'a RootNode, context: &'a QueryT::Context, ) -> GraphQLBatchResponse where diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs index 15d9f3a53..29c54587f 100644 --- a/juniper/src/lib.rs +++ b/juniper/src/lib.rs @@ -23,6 +23,8 @@ pub use {async_trait::async_trait, futures, serde, static_assertions as sa}; #[doc(inline)] pub use futures::future::{BoxFuture, LocalBoxFuture}; +pub use arcstr::{self, ArcStr}; + // Depend on juniper_codegen and re-export everything in it. // This allows users to just depend on juniper and get the derive // functionality automatically. @@ -198,7 +200,7 @@ where pub async fn execute<'a, S, QueryT, MutationT, SubscriptionT>( document_source: &'a str, operation_name: Option<&str>, - root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>, + root_node: &'a RootNode, variables: &Variables, context: &QueryT::Context, ) -> Result<(Value, Vec>), GraphQLError> @@ -249,7 +251,7 @@ where pub async fn resolve_into_stream<'a, S, QueryT, MutationT, SubscriptionT>( document_source: &'a str, operation_name: Option<&str>, - root_node: &'a RootNode<'a, QueryT, MutationT, SubscriptionT, S>, + root_node: &'a RootNode, variables: &Variables, context: &'a QueryT::Context, ) -> Result<(Value>, Vec>), GraphQLError> diff --git a/juniper/src/parser/document.rs b/juniper/src/parser/document.rs index 9479b2926..4bae92f22 100644 --- a/juniper/src/parser/document.rs +++ b/juniper/src/parser/document.rs @@ -1,5 +1,3 @@ -use std::borrow::Cow; - use crate::ast::{ Arguments, Definition, Directive, Field, Fragment, FragmentSpread, InlineFragment, InputValue, Operation, OperationType, OwnedDocument, Selection, Type, VariableDefinition, @@ -19,9 +17,9 @@ use crate::{ }; #[doc(hidden)] -pub fn parse_document_source<'a, 'b, S>( +pub fn parse_document_source<'a, S>( s: &'a str, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> UnlocatedParseResult> where S: ScalarValue, @@ -31,9 +29,9 @@ where parse_document(&mut parser, schema) } -fn parse_document<'a, 'b, S>( +fn parse_document<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> UnlocatedParseResult> where S: ScalarValue, @@ -49,9 +47,9 @@ where } } -fn parse_definition<'a, 'b, S>( +fn parse_definition<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> UnlocatedParseResult> where S: ScalarValue, @@ -70,9 +68,9 @@ where } } -fn parse_operation_definition<'a, 'b, S>( +fn parse_operation_definition<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> ParseResult> where S: ScalarValue, @@ -125,9 +123,9 @@ where } } -fn parse_fragment_definition<'a, 'b, S>( +fn parse_fragment_definition<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> ParseResult> where S: ScalarValue, @@ -167,10 +165,10 @@ where )) } -fn parse_optional_selection_set<'a, 'b, S>( +fn parse_optional_selection_set<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, - fields: Option<&[&MetaField<'b, S>]>, + schema: &SchemaType, + fields: Option<&[&MetaField]>, ) -> OptionParseResult>> where S: ScalarValue, @@ -182,10 +180,10 @@ where } } -fn parse_selection_set<'a, 'b, S>( +fn parse_selection_set<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, - fields: Option<&[&MetaField<'b, S>]>, + schema: &SchemaType, + fields: Option<&[&MetaField]>, ) -> ParseResult>> where S: ScalarValue, @@ -197,10 +195,10 @@ where ) } -fn parse_selection<'a, 'b, S>( +fn parse_selection<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, - fields: Option<&[&MetaField<'b, S>]>, + schema: &SchemaType, + fields: Option<&[&MetaField]>, ) -> UnlocatedParseResult> where S: ScalarValue, @@ -211,10 +209,10 @@ where } } -fn parse_fragment<'a, 'b, S>( +fn parse_fragment<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, - fields: Option<&[&MetaField<'b, S>]>, + schema: &SchemaType, + fields: Option<&[&MetaField]>, ) -> UnlocatedParseResult> where S: ScalarValue, @@ -290,10 +288,10 @@ where } } -fn parse_field<'a, 'b, S>( +fn parse_field<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, - fields: Option<&[&MetaField<'b, S>]>, + schema: &SchemaType, + fields: Option<&[&MetaField]>, ) -> ParseResult> where S: ScalarValue, @@ -341,10 +339,10 @@ where )) } -fn parse_arguments<'a, 'b, S>( +fn parse_arguments<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, - arguments: Option<&[Argument<'b, S>]>, + schema: &SchemaType, + arguments: Option<&[Argument]>, ) -> OptionParseResult> where S: ScalarValue, @@ -366,10 +364,10 @@ where } } -fn parse_argument<'a, 'b, S>( +fn parse_argument<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, - arguments: Option<&[Argument<'b, S>]>, + schema: &SchemaType, + arguments: Option<&[Argument]>, ) -> ParseResult<(Spanning<&'a str>, Spanning>)> where S: ScalarValue, @@ -400,9 +398,9 @@ fn parse_operation_type(parser: &mut Parser<'_>) -> ParseResult { } } -fn parse_variable_definitions<'a, 'b, S>( +fn parse_variable_definitions<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> OptionParseResult> where S: ScalarValue, @@ -424,9 +422,9 @@ where } } -fn parse_variable_definition<'a, 'b, S>( +fn parse_variable_definition<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> ParseResult<(Spanning<&'a str>, VariableDefinition<'a, S>)> where S: ScalarValue, @@ -462,9 +460,9 @@ where )) } -fn parse_directives<'a, 'b, S>( +fn parse_directives<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> OptionParseResult>>> where S: ScalarValue, @@ -481,9 +479,9 @@ where } } -fn parse_directive<'a, 'b, S>( +fn parse_directive<'a, S>( parser: &mut Parser<'a>, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> ParseResult> where S: ScalarValue, @@ -509,7 +507,7 @@ where )) } -pub fn parse_type<'a>(parser: &mut Parser<'a>) -> ParseResult> { +pub fn parse_type<'a>(parser: &mut Parser<'a>) -> ParseResult> { let parsed_type = if let Some(Spanning { span: start_span, .. }) = parser.skip(&Token::BracketOpen)? @@ -522,7 +520,7 @@ pub fn parse_type<'a>(parser: &mut Parser<'a>) -> ParseResult> { Type::List(Box::new(inner_type.item), None), ) } else { - parser.expect_name()?.map(|s| Type::Named(Cow::Borrowed(s))) + parser.expect_name()?.map(Type::Named) }; Ok(match *parser.peek() { @@ -534,13 +532,16 @@ pub fn parse_type<'a>(parser: &mut Parser<'a>) -> ParseResult> { }) } -fn wrap_non_null<'a>(parser: &mut Parser<'a>, inner: Spanning>) -> ParseResult> { +fn wrap_non_null<'a>( + parser: &mut Parser<'a>, + inner: Spanning>, +) -> ParseResult> { let end_pos = &parser.expect(&Token::ExclamationMark)?.span.end; let wrapped = match inner.item { Type::Named(name) => Type::NonNullNamed(name), Type::List(l, expected_size) => Type::NonNullList(l, expected_size), - t => t, + ty @ (Type::NonNullList(..) | Type::NonNullNamed(..)) => ty, }; Ok(Spanning::start_end(&inner.span.start, end_pos, wrapped)) diff --git a/juniper/src/parser/tests/value.rs b/juniper/src/parser/tests/value.rs index fdb98a8f2..66c3d547d 100644 --- a/juniper/src/parser/tests/value.rs +++ b/juniper/src/parser/tests/value.rs @@ -52,12 +52,12 @@ impl Query { } } -fn scalar_meta(name: &'static str) -> MetaType<'static> +fn scalar_meta(name: &'static str) -> MetaType where T: FromInputValue + ParseScalarValue, T::Error: IntoFieldError, { - MetaType::Scalar(ScalarMeta::new::(name.into())) + MetaType::Scalar(ScalarMeta::new::(name)) } fn parse_value(s: &str, meta: &MetaType) -> Spanning> @@ -116,7 +116,7 @@ fn input_value_literals() { ), ); let values = &[EnumValue::new("enum_value")]; - let e: EnumMeta = EnumMeta::new::("TestEnum".into(), values); + let e: EnumMeta = EnumMeta::new::("TestEnum", values); assert_eq!( parse_value::("enum_value", &MetaType::Enum(e)), @@ -176,7 +176,7 @@ fn input_value_literals() { Argument::new("key", Type::NonNullNamed("Int".into())), Argument::new("other", Type::NonNullNamed("Bar".into())), ]; - let meta = &MetaType::InputObject(InputObjectMeta::new::("foo".into(), &fields)); + let meta = &MetaType::InputObject(InputObjectMeta::new::("foo", &fields)); assert_eq!( parse_value::("{}", meta), Spanning::start_end( diff --git a/juniper/src/parser/value.rs b/juniper/src/parser/value.rs index 53a8103fe..3090f0984 100644 --- a/juniper/src/parser/value.rs +++ b/juniper/src/parser/value.rs @@ -11,11 +11,11 @@ use crate::{ use super::utils::Span; -pub fn parse_value_literal<'b, S>( +pub fn parse_value_literal( parser: &mut Parser<'_>, is_const: bool, - schema: &'b SchemaType<'b, S>, - tpe: Option<&MetaType<'b, S>>, + schema: &SchemaType, + tpe: Option<&MetaType>, ) -> ParseResult> where S: ScalarValue, @@ -117,11 +117,11 @@ where } } -fn parse_list_literal<'b, S>( +fn parse_list_literal( parser: &mut Parser<'_>, is_const: bool, - schema: &'b SchemaType<'b, S>, - tpe: Option<&MetaType<'b, S>>, + schema: &SchemaType, + tpe: Option<&MetaType>, ) -> ParseResult> where S: ScalarValue, @@ -135,11 +135,11 @@ where .map(InputValue::parsed_list)) } -fn parse_object_literal<'b, S>( +fn parse_object_literal( parser: &mut Parser<'_>, is_const: bool, - schema: &'b SchemaType<'b, S>, - object_tpe: Option<&InputObjectMeta<'b, S>>, + schema: &SchemaType, + object_tpe: Option<&InputObjectMeta>, ) -> ParseResult> where S: ScalarValue, @@ -153,11 +153,11 @@ where .map(|items| InputValue::parsed_object(items.into_iter().map(|s| s.item).collect()))) } -fn parse_object_field<'b, S>( +fn parse_object_field( parser: &mut Parser<'_>, is_const: bool, - schema: &'b SchemaType<'b, S>, - object_meta: Option<&InputObjectMeta<'b, S>>, + schema: &SchemaType, + object_meta: Option<&InputObjectMeta>, ) -> ParseResult<(Spanning, Spanning>)> where S: ScalarValue, @@ -197,10 +197,10 @@ where )) } -fn parse_scalar_literal_by_infered_type<'b, S>( +fn parse_scalar_literal_by_infered_type( token: ScalarToken<'_>, span: Span, - schema: &'b SchemaType<'b, S>, + schema: &SchemaType, ) -> ParseResult> where S: ScalarValue, diff --git a/juniper/src/schema/meta.rs b/juniper/src/schema/meta.rs index 8e1f5e9dd..2d6e27d52 100644 --- a/juniper/src/schema/meta.rs +++ b/juniper/src/schema/meta.rs @@ -1,10 +1,11 @@ //! Types used to describe a `GraphQL` schema -use juniper::IntoFieldError; -use std::{borrow::Cow, fmt}; +use std::{borrow::ToOwned, fmt}; + +use arcstr::ArcStr; use crate::{ - FieldError, + FieldError, IntoFieldError, ast::{FromInputValue, InputValue, Type}, parser::{ParseError, ScalarToken}, schema::model::SchemaType, @@ -17,429 +18,60 @@ use crate::{ pub enum DeprecationStatus { /// The field/variant is not deprecated. Current, + /// The field/variant is deprecated, with an optional reason - Deprecated(Option), + Deprecated(Option), } impl DeprecationStatus { /// If this deprecation status indicates the item is deprecated. pub fn is_deprecated(&self) -> bool { match self { - DeprecationStatus::Current => false, - DeprecationStatus::Deprecated(_) => true, + Self::Current => false, + Self::Deprecated(_) => true, } } /// An optional reason for the deprecation, or none if `Current`. - pub fn reason(&self) -> Option<&str> { + pub fn reason(&self) -> Option<&ArcStr> { match self { - DeprecationStatus::Current => None, - DeprecationStatus::Deprecated(rsn) => rsn.as_deref(), + Self::Current => None, + Self::Deprecated(rsn) => rsn.as_ref(), } } } /// Scalar type metadata -pub struct ScalarMeta<'a, S> { +pub struct ScalarMeta { #[doc(hidden)] - pub name: Cow<'a, str>, + pub name: ArcStr, #[doc(hidden)] - pub description: Option, + pub description: Option, #[doc(hidden)] - pub specified_by_url: Option>, + pub specified_by_url: Option, pub(crate) try_parse_fn: InputValueParseFn, pub(crate) parse_fn: ScalarTokenParseFn, } -/// Shortcut for an [`InputValue`] parsing function. -pub type InputValueParseFn = for<'b> fn(&'b InputValue) -> Result<(), FieldError>; - -/// Shortcut for a [`ScalarToken`] parsing function. -pub type ScalarTokenParseFn = for<'b> fn(ScalarToken<'b>) -> Result; - -/// List type metadata -#[derive(Debug)] -pub struct ListMeta<'a> { - #[doc(hidden)] - pub of_type: Type<'a>, - - #[doc(hidden)] - pub expected_size: Option, -} - -/// Nullable type metadata -#[derive(Debug)] -pub struct NullableMeta<'a> { - #[doc(hidden)] - pub of_type: Type<'a>, -} - -/// Object type metadata -#[derive(Debug)] -pub struct ObjectMeta<'a, S> { - #[doc(hidden)] - pub name: Cow<'a, str>, - #[doc(hidden)] - pub description: Option, - #[doc(hidden)] - pub fields: Vec>, - #[doc(hidden)] - pub interface_names: Vec, -} - -/// Enum type metadata -pub struct EnumMeta<'a, S> { - #[doc(hidden)] - pub name: Cow<'a, str>, - #[doc(hidden)] - pub description: Option, - #[doc(hidden)] - pub values: Vec, - pub(crate) try_parse_fn: InputValueParseFn, -} - -/// Interface type metadata -#[derive(Debug)] -pub struct InterfaceMeta<'a, S> { - #[doc(hidden)] - pub name: Cow<'a, str>, - #[doc(hidden)] - pub description: Option, - #[doc(hidden)] - pub fields: Vec>, - #[doc(hidden)] - pub interface_names: Vec, -} - -/// Union type metadata -#[derive(Debug)] -pub struct UnionMeta<'a> { - #[doc(hidden)] - pub name: Cow<'a, str>, - #[doc(hidden)] - pub description: Option, - #[doc(hidden)] - pub of_type_names: Vec, -} - -/// Input object metadata -pub struct InputObjectMeta<'a, S> { - #[doc(hidden)] - pub name: Cow<'a, str>, - #[doc(hidden)] - pub description: Option, - #[doc(hidden)] - pub input_fields: Vec>, - pub(crate) try_parse_fn: InputValueParseFn, -} - -/// A placeholder for not-yet-registered types -/// -/// After a type's `meta` method has been called but before it has returned, a placeholder type -/// is inserted into a registry to indicate existence. -#[derive(Debug)] -pub struct PlaceholderMeta<'a> { - #[doc(hidden)] - pub of_type: Type<'a>, -} - -/// Generic type metadata -#[derive(Debug)] -pub enum MetaType<'a, S = DefaultScalarValue> { - #[doc(hidden)] - Scalar(ScalarMeta<'a, S>), - #[doc(hidden)] - List(ListMeta<'a>), - #[doc(hidden)] - Nullable(NullableMeta<'a>), - #[doc(hidden)] - Object(ObjectMeta<'a, S>), - #[doc(hidden)] - Enum(EnumMeta<'a, S>), - #[doc(hidden)] - Interface(InterfaceMeta<'a, S>), - #[doc(hidden)] - Union(UnionMeta<'a>), - #[doc(hidden)] - InputObject(InputObjectMeta<'a, S>), - #[doc(hidden)] - Placeholder(PlaceholderMeta<'a>), -} - -/// Metadata for a field -#[derive(Debug, Clone)] -pub struct Field<'a, S> { - #[doc(hidden)] - pub name: smartstring::alias::String, - #[doc(hidden)] - pub description: Option, - #[doc(hidden)] - pub arguments: Option>>, - #[doc(hidden)] - pub field_type: Type<'a>, - #[doc(hidden)] - pub deprecation_status: DeprecationStatus, -} - -impl Field<'_, S> { - /// Returns true if the type is built-in to GraphQL. - pub fn is_builtin(&self) -> bool { - // "used exclusively by GraphQL’s introspection system" - self.name.starts_with("__") - } -} - -/// Metadata for an argument to a field -#[derive(Debug, Clone)] -pub struct Argument<'a, S> { - #[doc(hidden)] - pub name: String, - #[doc(hidden)] - pub description: Option, - #[doc(hidden)] - pub arg_type: Type<'a>, - #[doc(hidden)] - pub default_value: Option>, -} - -impl Argument<'_, S> { - /// Returns true if the type is built-in to GraphQL. - pub fn is_builtin(&self) -> bool { - // "used exclusively by GraphQL’s introspection system" - self.name.starts_with("__") - } -} - -/// Metadata for a single value in an enum -#[derive(Debug, Clone)] -pub struct EnumValue { - /// The name of the enum value - /// - /// This is the string literal representation of the enum in responses. - pub name: String, - /// The optional description of the enum value. - /// - /// Note: this is not the description of the enum itself; it's the - /// description of this enum _value_. - pub description: Option, - /// Whether the field is deprecated or not, with an optional reason. - pub deprecation_status: DeprecationStatus, -} - -impl<'a, S> MetaType<'a, S> { - /// Access the name of the type, if applicable - /// - /// Lists, non-null wrappers, and placeholders don't have names. - pub fn name(&self) -> Option<&str> { - match *self { - MetaType::Scalar(ScalarMeta { ref name, .. }) - | MetaType::Object(ObjectMeta { ref name, .. }) - | MetaType::Enum(EnumMeta { ref name, .. }) - | MetaType::Interface(InterfaceMeta { ref name, .. }) - | MetaType::Union(UnionMeta { ref name, .. }) - | MetaType::InputObject(InputObjectMeta { ref name, .. }) => Some(name), - _ => None, - } - } - - /// Access the description of the type, if applicable - /// - /// Lists, nullable wrappers, and placeholders don't have names. - pub fn description(&self) -> Option<&str> { - match self { - MetaType::Scalar(ScalarMeta { description, .. }) - | MetaType::Object(ObjectMeta { description, .. }) - | MetaType::Enum(EnumMeta { description, .. }) - | MetaType::Interface(InterfaceMeta { description, .. }) - | MetaType::Union(UnionMeta { description, .. }) - | MetaType::InputObject(InputObjectMeta { description, .. }) => description.as_deref(), - _ => None, - } - } - - /// Accesses the [specification URL][0], if applicable. - /// - /// Only custom GraphQL scalars can have a [specification URL][0]. - /// - /// [0]: https://spec.graphql.org/October2021#sec--specifiedBy - pub fn specified_by_url(&self) -> Option<&str> { - match self { - Self::Scalar(ScalarMeta { - specified_by_url, .. - }) => specified_by_url.as_deref(), - _ => None, - } - } - - /// Construct a `TypeKind` for a given type - /// - /// # Panics - /// - /// Panics if the type represents a placeholder or nullable type. - pub fn type_kind(&self) -> TypeKind { - match *self { - MetaType::Scalar(_) => TypeKind::Scalar, - MetaType::List(_) => TypeKind::List, - MetaType::Nullable(_) => panic!("Can't take type_kind of nullable meta type"), - MetaType::Object(_) => TypeKind::Object, - MetaType::Enum(_) => TypeKind::Enum, - MetaType::Interface(_) => TypeKind::Interface, - MetaType::Union(_) => TypeKind::Union, - MetaType::InputObject(_) => TypeKind::InputObject, - MetaType::Placeholder(_) => panic!("Can't take type_kind of placeholder meta type"), - } - } - - /// Access a field's meta data given its name - /// - /// Only objects and interfaces have fields. This method always returns `None` for other types. - pub fn field_by_name(&self, name: &str) -> Option<&Field> { - match *self { - MetaType::Object(ObjectMeta { ref fields, .. }) - | MetaType::Interface(InterfaceMeta { ref fields, .. }) => { - fields.iter().find(|f| f.name == name) - } - _ => None, - } - } - - /// Access an input field's meta data given its name - /// - /// Only input objects have input fields. This method always returns `None` for other types. - pub fn input_field_by_name(&self, name: &str) -> Option<&Argument> { - match *self { - MetaType::InputObject(InputObjectMeta { - ref input_fields, .. - }) => input_fields.iter().find(|f| f.name == name), - _ => None, - } - } - - /// Construct a `Type` literal instance based on the metadata - pub fn as_type(&self) -> Type<'a> { - match *self { - MetaType::Scalar(ScalarMeta { ref name, .. }) - | MetaType::Object(ObjectMeta { ref name, .. }) - | MetaType::Enum(EnumMeta { ref name, .. }) - | MetaType::Interface(InterfaceMeta { ref name, .. }) - | MetaType::Union(UnionMeta { ref name, .. }) - | MetaType::InputObject(InputObjectMeta { ref name, .. }) => { - Type::NonNullNamed(name.clone()) - } - MetaType::List(ListMeta { - ref of_type, - expected_size, - }) => Type::NonNullList(Box::new(of_type.clone()), expected_size), - MetaType::Nullable(NullableMeta { ref of_type }) => match *of_type { - Type::NonNullNamed(ref inner) => Type::Named(inner.clone()), - Type::NonNullList(ref inner, expected_size) => { - Type::List(inner.clone(), expected_size) - } - ref t => t.clone(), - }, - MetaType::Placeholder(PlaceholderMeta { ref of_type }) => of_type.clone(), - } - } - - /// Access the input value parse function, if applicable - /// - /// An input value parse function is a function that takes an `InputValue` instance and returns - /// `true` if it can be parsed as the provided type. - /// - /// Only scalars, enums, and input objects have parse functions. - pub fn input_value_parse_fn(&self) -> Option> { - match *self { - MetaType::Scalar(ScalarMeta { - ref try_parse_fn, .. - }) - | MetaType::Enum(EnumMeta { - ref try_parse_fn, .. - }) - | MetaType::InputObject(InputObjectMeta { - ref try_parse_fn, .. - }) => Some(*try_parse_fn), - _ => None, - } - } - - /// Returns true if the type is a composite type - /// - /// Objects, interfaces, and unions are composite. - pub fn is_composite(&self) -> bool { - matches!( - *self, - MetaType::Object(_) | MetaType::Interface(_) | MetaType::Union(_) - ) - } - - /// Returns true if the type can occur in leaf positions in queries - /// - /// Only enums and scalars are leaf types. - pub fn is_leaf(&self) -> bool { - matches!(*self, MetaType::Enum(_) | MetaType::Scalar(_)) - } - - /// Returns true if the type is abstract - /// - /// Only interfaces and unions are abstract types. - pub fn is_abstract(&self) -> bool { - matches!(*self, MetaType::Interface(_) | MetaType::Union(_)) - } - - /// Returns true if the type can be used in input positions, e.g. arguments or variables - /// - /// Only scalars, enums, and input objects are input types. - pub fn is_input(&self) -> bool { - matches!( - *self, - MetaType::Scalar(_) | MetaType::Enum(_) | MetaType::InputObject(_) - ) - } - - /// Returns true if the type is built-in to GraphQL. - pub fn is_builtin(&self) -> bool { - if let Some(name) = self.name() { - // "used exclusively by GraphQL’s introspection system" - { - name.starts_with("__") || - // https://spec.graphql.org/October2021#sec-Scalars - name == "Boolean" || name == "String" || name == "Int" || name == "Float" || name == "ID" || - // Our custom empty markers - name == "_EmptyMutation" || name == "_EmptySubscription" - } - } else { - false - } - } - - pub(crate) fn fields<'b>(&self, schema: &'b SchemaType) -> Option>> { - schema - .lookup_type(&self.as_type()) - .and_then(|tpe| match *tpe { - MetaType::Interface(ref i) => Some(i.fields.iter().collect()), - MetaType::Object(ref o) => Some(o.fields.iter().collect()), - MetaType::Union(ref u) => Some( - u.of_type_names - .iter() - .filter_map(|n| schema.concrete_type_by_name(n)) - .filter_map(|t| t.fields(schema)) - .flatten() - .collect(), - ), - _ => None, - }) +impl fmt::Debug for ScalarMeta { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("ScalarMeta") + .field("name", &self.name) + .field("description", &self.description) + .field("specified_by_url", &self.specified_by_url) + .finish_non_exhaustive() } } -impl<'a, S> ScalarMeta<'a, S> { +impl ScalarMeta { /// Builds a new [`ScalarMeta`] type with the specified `name`. - pub fn new(name: Cow<'a, str>) -> Self + pub fn new(name: impl Into) -> Self where T: FromInputValue + ParseScalarValue, T::Error: IntoFieldError, { Self { - name, + name: name.into(), description: None, specified_by_url: None, try_parse_fn: try_parse_fn::, @@ -451,7 +83,7 @@ impl<'a, S> ScalarMeta<'a, S> { /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } @@ -462,23 +94,39 @@ impl<'a, S> ScalarMeta<'a, S> { /// /// [0]: https://spec.graphql.org/October2021#sec--specifiedBy #[must_use] - pub fn specified_by_url(mut self, url: impl Into>) -> Self { + pub fn specified_by_url(mut self, url: impl Into) -> Self { self.specified_by_url = Some(url.into()); self } /// Wraps this [`ScalarMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::Scalar(self) } } -impl<'a> ListMeta<'a> { - /// Build a new [`ListMeta`] type by wrapping the specified [`Type`]. +/// Shortcut for an [`InputValue`] parsing function. +pub type InputValueParseFn = for<'b> fn(&'b InputValue) -> Result<(), FieldError>; + +/// Shortcut for a [`ScalarToken`] parsing function. +pub type ScalarTokenParseFn = for<'b> fn(ScalarToken<'b>) -> Result; + +/// List type metadata +#[derive(Debug)] +pub struct ListMeta { + #[doc(hidden)] + pub of_type: Type, + + #[doc(hidden)] + pub expected_size: Option, +} + +impl ListMeta { + /// Builds a new [`ListMeta`] type by wrapping the specified [`Type`]. /// - /// Specifying `expected_size` will be used to ensure that values of this - /// type will always match it. - pub fn new(of_type: Type<'a>, expected_size: Option) -> Self { + /// Specifying `expected_size` will be used to ensure that values of this type will always match + /// it. + pub fn new(of_type: Type, expected_size: Option) -> Self { Self { of_type, expected_size, @@ -486,31 +134,51 @@ impl<'a> ListMeta<'a> { } /// Wraps this [`ListMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::List(self) } } -impl<'a> NullableMeta<'a> { - /// Build a new [`NullableMeta`] type by wrapping the specified [`Type`]. - pub fn new(of_type: Type<'a>) -> Self { +/// Nullable type metadata +#[derive(Debug)] +pub struct NullableMeta { + #[doc(hidden)] + pub of_type: Type, +} + +impl NullableMeta { + /// Builds a new [`NullableMeta`] type by wrapping the specified [`Type`]. + pub fn new(of_type: Type) -> Self { Self { of_type } } /// Wraps this [`NullableMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::Nullable(self) } } -impl<'a, S> ObjectMeta<'a, S> { - /// Build a new [`ObjectMeta`] type with the specified `name` and `fields`. - pub fn new(name: Cow<'a, str>, fields: &[Field<'a, S>]) -> Self +/// Object type metadata +#[derive(Debug)] +pub struct ObjectMeta { + #[doc(hidden)] + pub name: ArcStr, + #[doc(hidden)] + pub description: Option, + #[doc(hidden)] + pub fields: Vec>, + #[doc(hidden)] + pub interface_names: Vec, +} + +impl ObjectMeta { + /// Builds a new [`ObjectMeta`] type with the specified `name` and `fields`. + pub fn new(name: impl Into, fields: &[Field]) -> Self where S: Clone, { Self { - name, + name: name.into(), description: None, fields: fields.to_vec(), interface_names: vec![], @@ -521,16 +189,16 @@ impl<'a, S> ObjectMeta<'a, S> { /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } - /// Set the `interfaces` this [`ObjectMeta`] type implements. + /// Sets the `interfaces` this [`ObjectMeta`] type implements. /// /// Overwrites any previously set list of interfaces. #[must_use] - pub fn interfaces(mut self, interfaces: &[Type<'a>]) -> Self { + pub fn interfaces(mut self, interfaces: &[Type]) -> Self { self.interface_names = interfaces .iter() .map(|t| t.innermost_name().into()) @@ -539,21 +207,41 @@ impl<'a, S> ObjectMeta<'a, S> { } /// Wraps this [`ObjectMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::Object(self) } } -impl<'a, S> EnumMeta<'a, S> { - /// Build a new [`EnumMeta`] type with the specified `name` and possible - /// `values`. - pub fn new(name: Cow<'a, str>, values: &[EnumValue]) -> Self +/// Enum type metadata +pub struct EnumMeta { + #[doc(hidden)] + pub name: ArcStr, + #[doc(hidden)] + pub description: Option, + #[doc(hidden)] + pub values: Vec, + pub(crate) try_parse_fn: InputValueParseFn, +} + +impl fmt::Debug for EnumMeta { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("EnumMeta") + .field("name", &self.name) + .field("description", &self.description) + .field("values", &self.values) + .finish_non_exhaustive() + } +} + +impl EnumMeta { + /// Builds a new [`EnumMeta`] type with the specified `name` and possible `values`. + pub fn new(name: impl Into, values: &[EnumValue]) -> Self where T: FromInputValue, T::Error: IntoFieldError, { Self { - name, + name: name.into(), description: None, values: values.to_owned(), try_parse_fn: try_parse_fn::, @@ -564,26 +252,38 @@ impl<'a, S> EnumMeta<'a, S> { /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } /// Wraps this [`EnumMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::Enum(self) } } -impl<'a, S> InterfaceMeta<'a, S> { - /// Builds a new [`InterfaceMeta`] type with the specified `name` and - /// `fields`. - pub fn new(name: Cow<'a, str>, fields: &[Field<'a, S>]) -> Self +/// Interface type metadata +#[derive(Debug)] +pub struct InterfaceMeta { + #[doc(hidden)] + pub name: ArcStr, + #[doc(hidden)] + pub description: Option, + #[doc(hidden)] + pub fields: Vec>, + #[doc(hidden)] + pub interface_names: Vec, +} + +impl InterfaceMeta { + /// Builds a new [`InterfaceMeta`] type with the specified `name` and `fields`. + pub fn new(name: impl Into, fields: &[Field]) -> Self where S: Clone, { Self { - name, + name: name.into(), description: None, fields: fields.to_vec(), interface_names: Vec::new(), @@ -594,7 +294,7 @@ impl<'a, S> InterfaceMeta<'a, S> { /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } @@ -603,7 +303,7 @@ impl<'a, S> InterfaceMeta<'a, S> { /// /// Overwrites any previously set list of interfaces. #[must_use] - pub fn interfaces(mut self, interfaces: &[Type<'a>]) -> Self { + pub fn interfaces(mut self, interfaces: &[Type]) -> Self { self.interface_names = interfaces .iter() .map(|t| t.innermost_name().into()) @@ -612,17 +312,27 @@ impl<'a, S> InterfaceMeta<'a, S> { } /// Wraps this [`InterfaceMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::Interface(self) } } -impl<'a> UnionMeta<'a> { - /// Build a new [`UnionMeta`] type with the specified `name` and possible - /// [`Type`]s. - pub fn new(name: Cow<'a, str>, of_types: &[Type]) -> Self { +/// Union type metadata +#[derive(Debug)] +pub struct UnionMeta { + #[doc(hidden)] + pub name: ArcStr, + #[doc(hidden)] + pub description: Option, + #[doc(hidden)] + pub of_type_names: Vec, +} + +impl UnionMeta { + /// Builds a new [`UnionMeta`] type with the specified `name` and possible [`Type`]s. + pub fn new(name: impl Into, of_types: &[Type]) -> Self { Self { - name, + name: name.into(), description: None, of_type_names: of_types.iter().map(|t| t.innermost_name().into()).collect(), } @@ -632,55 +342,100 @@ impl<'a> UnionMeta<'a> { /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } /// Wraps this [`UnionMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::Union(self) } } -impl<'a, S> InputObjectMeta<'a, S> { - /// Builds a new [`InputObjectMeta`] type with the specified `name` and - /// `input_fields`. - pub fn new(name: Cow<'a, str>, input_fields: &[Argument<'a, S>]) -> Self +/// Input object metadata +pub struct InputObjectMeta { + #[doc(hidden)] + pub name: ArcStr, + #[doc(hidden)] + pub description: Option, + #[doc(hidden)] + pub input_fields: Vec>, + pub(crate) try_parse_fn: InputValueParseFn, +} + +impl fmt::Debug for InputObjectMeta { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("InputObjectMeta") + .field("name", &self.name) + .field("description", &self.description) + .field("input_fields", &self.input_fields) + .finish_non_exhaustive() + } +} + +impl InputObjectMeta { + /// Builds a new [`InputObjectMeta`] type with the specified `name` and `input_fields`. + pub fn new(name: impl Into, input_fields: &[Argument]) -> Self where T: FromInputValue, T::Error: IntoFieldError, S: Clone, { Self { - name, + name: name.into(), description: None, input_fields: input_fields.to_vec(), try_parse_fn: try_parse_fn::, } } - /// Set the `description` of this [`InputObjectMeta`] type. + /// Sets the `description` of this [`InputObjectMeta`] type. /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } /// Wraps this [`InputObjectMeta`] type into a generic [`MetaType`]. - pub fn into_meta(self) -> MetaType<'a, S> { + pub fn into_meta(self) -> MetaType { MetaType::InputObject(self) } } -impl<'a, S> Field<'a, S> { - /// Set the `description` of this [`Field`]. +/// A placeholder for not-yet-registered types +/// +/// After a type's `meta` method has been called but before it has returned, a placeholder type +/// is inserted into a registry to indicate existence. +#[derive(Debug)] +pub struct PlaceholderMeta { + #[doc(hidden)] + pub of_type: Type, +} + +/// Metadata for a field +#[derive(Debug, Clone)] +pub struct Field { + #[doc(hidden)] + pub name: ArcStr, + #[doc(hidden)] + pub description: Option, + #[doc(hidden)] + pub arguments: Option>>, + #[doc(hidden)] + pub field_type: Type, + #[doc(hidden)] + pub deprecation_status: DeprecationStatus, +} + +impl Field { + /// Sets the `description` of this [`Field`]. /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } @@ -689,7 +444,7 @@ impl<'a, S> Field<'a, S> { /// /// Arguments are unordered and can't contain duplicates by name. #[must_use] - pub fn argument(mut self, argument: Argument<'a, S>) -> Self { + pub fn argument(mut self, argument: Argument) -> Self { match self.arguments { None => { self.arguments = Some(vec![argument]); @@ -701,19 +456,39 @@ impl<'a, S> Field<'a, S> { self } + /// Indicates whether this [`Field`] is GraphQL built-in. + #[must_use] + pub fn is_builtin(&self) -> bool { + // "used exclusively by GraphQL’s introspection system" + self.name.starts_with("__") + } + /// Sets this [`Field`] as deprecated with an optional `reason`. /// /// Overwrites any previously set deprecation reason. #[must_use] - pub fn deprecated(mut self, reason: Option<&str>) -> Self { + pub fn deprecated(mut self, reason: Option>) -> Self { self.deprecation_status = DeprecationStatus::Deprecated(reason.map(Into::into)); self } } -impl<'a, S> Argument<'a, S> { +/// Metadata for an argument to a field +#[derive(Debug, Clone)] +pub struct Argument { + #[doc(hidden)] + pub name: ArcStr, + #[doc(hidden)] + pub description: Option, + #[doc(hidden)] + pub arg_type: Type, + #[doc(hidden)] + pub default_value: Option>, +} + +impl Argument { /// Builds a new [`Argument`] of the given [`Type`] with the given `name`. - pub fn new(name: &str, arg_type: Type<'a>) -> Self { + pub fn new(name: impl Into, arg_type: Type) -> Self { Self { name: name.into(), description: None, @@ -726,12 +501,19 @@ impl<'a, S> Argument<'a, S> { /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } - /// Set the default value of this [`Argument`]. + /// Indicates whether this [`Argument`] is GraphQL built-in. + #[must_use] + pub fn is_builtin(&self) -> bool { + // "used exclusively by GraphQL’s introspection system" + self.name.starts_with("__") + } + + /// Sets the default value of this [`Argument`]. /// /// Overwrites any previously set default value. #[must_use] @@ -741,9 +523,27 @@ impl<'a, S> Argument<'a, S> { } } +/// Metadata for a single value in an enum +#[derive(Debug, Clone)] +pub struct EnumValue { + /// The name of the enum value + /// + /// This is the string literal representation of the enum in responses. + pub name: ArcStr, + + /// The optional description of the enum value. + /// + /// Note: this is not the description of the enum itself; it's the + /// description of this enum _value_. + pub description: Option, + + /// Whether the field is deprecated or not, with an optional reason. + pub deprecation_status: DeprecationStatus, +} + impl EnumValue { /// Constructs a new [`EnumValue`] with the provided `name`. - pub fn new(name: &str) -> Self { + pub fn new(name: impl Into) -> Self { Self { name: name.into(), description: None, @@ -755,7 +555,7 @@ impl EnumValue { /// /// Overwrites any previously set description. #[must_use] - pub fn description(mut self, description: &str) -> Self { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } @@ -764,38 +564,260 @@ impl EnumValue { /// /// Overwrites any previously set deprecation reason. #[must_use] - pub fn deprecated(mut self, reason: Option<&str>) -> Self { + pub fn deprecated(mut self, reason: Option>) -> Self { self.deprecation_status = DeprecationStatus::Deprecated(reason.map(Into::into)); self } } -impl fmt::Debug for ScalarMeta<'_, S> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("ScalarMeta") - .field("name", &self.name) - .field("description", &self.description) - .finish() - } +/// Generic type metadata +#[derive(Debug)] +pub enum MetaType { + #[doc(hidden)] + Scalar(ScalarMeta), + #[doc(hidden)] + List(ListMeta), + #[doc(hidden)] + Nullable(NullableMeta), + #[doc(hidden)] + Object(ObjectMeta), + #[doc(hidden)] + Enum(EnumMeta), + #[doc(hidden)] + Interface(InterfaceMeta), + #[doc(hidden)] + Union(UnionMeta), + #[doc(hidden)] + InputObject(InputObjectMeta), + #[doc(hidden)] + Placeholder(PlaceholderMeta), } -impl fmt::Debug for EnumMeta<'_, S> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("EnumMeta") - .field("name", &self.name) - .field("description", &self.description) - .field("values", &self.values) - .finish() +impl MetaType { + /// Returns the name of the represented type, if applicable. + /// + /// [Lists][`ListMeta`], [`null`ables][`NullableMeta`] and [placeholders][`PlaceholderMeta`] + /// don't have a name. + pub fn name(&self) -> Option<&ArcStr> { + match self { + Self::Enum(EnumMeta { name, .. }) + | Self::InputObject(InputObjectMeta { name, .. }) + | Self::Interface(InterfaceMeta { name, .. }) + | Self::Object(ObjectMeta { name, .. }) + | Self::Scalar(ScalarMeta { name, .. }) + | Self::Union(UnionMeta { name, .. }) => Some(name), + Self::List(..) | Self::Nullable(..) | Self::Placeholder(..) => None, + } } -} -impl fmt::Debug for InputObjectMeta<'_, S> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("InputObjectMeta") - .field("name", &self.name) - .field("description", &self.description) - .field("input_fields", &self.input_fields) - .finish() + /// Returns the description of the represented type, if applicable. + /// + /// [Lists][`ListMeta`], [`null`ables][`NullableMeta`] and [placeholders][`PlaceholderMeta`] + /// don't have a description. + pub fn description(&self) -> Option<&ArcStr> { + match self { + Self::Enum(EnumMeta { description, .. }) + | Self::InputObject(InputObjectMeta { description, .. }) + | Self::Interface(InterfaceMeta { description, .. }) + | Self::Object(ObjectMeta { description, .. }) + | Self::Scalar(ScalarMeta { description, .. }) + | Self::Union(UnionMeta { description, .. }) => description.as_ref(), + Self::List(..) | Self::Nullable(..) | Self::Placeholder(..) => None, + } + } + + /// Returns the [specification URL][0] of the represented type, if applicable. + /// + /// Only custom GraphQL scalars can have a [specification URL][0]. + /// + /// [0]: https://spec.graphql.org/October2021#sec--specifiedBy + pub fn specified_by_url(&self) -> Option<&ArcStr> { + match self { + Self::Scalar(ScalarMeta { + specified_by_url, .. + }) => specified_by_url.as_ref(), + Self::Enum(..) + | Self::InputObject(..) + | Self::Interface(..) + | Self::List(..) + | Self::Nullable(..) + | Self::Object(..) + | Self::Placeholder(..) + | Self::Union(..) => None, + } + } + + /// Construct a [`TypeKind`] out of this [`MetaType`]. + /// + /// # Panics + /// + /// If this is [`MetaType::Nullable`] or [``MetaType::Placeholder`]. + pub fn type_kind(&self) -> TypeKind { + match self { + Self::Scalar(..) => TypeKind::Scalar, + Self::List(..) => TypeKind::List, + Self::Nullable(..) => panic!("сan't take `type_kind` of `MetaType::Nullable`"), + Self::Object(..) => TypeKind::Object, + Self::Enum(..) => TypeKind::Enum, + Self::Interface(..) => TypeKind::Interface, + Self::Union(..) => TypeKind::Union, + Self::InputObject(..) => TypeKind::InputObject, + Self::Placeholder(..) => panic!("сan't take `type_kind` of `MetaType::Placeholder`"), + } + } + + /// Returns a [`Field`]'s metadata by its `name`. + /// + /// Only [objects][`ObjectMeta`] and [interfaces][`InterfaceMeta`] have fields. + pub fn field_by_name(&self, name: &str) -> Option<&Field> { + match self { + Self::Interface(InterfaceMeta { fields, .. }) + | Self::Object(ObjectMeta { fields, .. }) => fields.iter().find(|f| f.name == name), + Self::Enum(..) + | Self::InputObject(..) + | Self::List(..) + | Self::Nullable(..) + | Self::Placeholder(..) + | Self::Scalar(..) + | Self::Union(..) => None, + } + } + + /// Returns an input field's metadata by its `name`. + /// + /// Only [input objects][`InputObjectMeta`] have input fields. + pub fn input_field_by_name(&self, name: &str) -> Option<&Argument> { + match self { + Self::InputObject(InputObjectMeta { input_fields, .. }) => { + input_fields.iter().find(|f| f.name == name) + } + Self::Enum(..) + | Self::Interface(..) + | Self::List(..) + | Self::Nullable(..) + | Self::Object(..) + | Self::Placeholder(..) + | Self::Scalar(..) + | Self::Union(..) => None, + } + } + + /// Construct a [`Type`] literal out of this [`MetaType`]. + pub fn as_type(&self) -> Type { + match self { + Self::Enum(EnumMeta { name, .. }) + | Self::InputObject(InputObjectMeta { name, .. }) + | Self::Interface(InterfaceMeta { name, .. }) + | Self::Object(ObjectMeta { name, .. }) + | Self::Scalar(ScalarMeta { name, .. }) + | Self::Union(UnionMeta { name, .. }) => Type::NonNullNamed(name.clone()), + Self::List(ListMeta { + of_type, + expected_size, + }) => Type::NonNullList(Box::new(of_type.clone()), *expected_size), + Self::Nullable(NullableMeta { of_type }) => match of_type { + Type::NonNullNamed(inner) => Type::Named(inner.clone()), + Type::NonNullList(inner, expected_size) => { + Type::List(inner.clone(), *expected_size) + } + ty @ (Type::List(..) | Type::Named(..)) => ty.clone(), + }, + Self::Placeholder(PlaceholderMeta { of_type }) => of_type.clone(), + } + } + + /// Returns the [`InputValueParseFn`] of the represented type, if applicable. + /// + /// Only [scalars][`ScalarMeta`], [enums][`EnumMeta`] and [input objects][`InputObjectMeta`] + /// have an [`InputValueParseFn`]. + pub fn input_value_parse_fn(&self) -> Option> { + match self { + Self::Enum(EnumMeta { try_parse_fn, .. }) + | Self::InputObject(InputObjectMeta { try_parse_fn, .. }) + | Self::Scalar(ScalarMeta { try_parse_fn, .. }) => Some(*try_parse_fn), + Self::Interface(..) + | Self::List(..) + | Self::Nullable(..) + | Self::Object(..) + | Self::Placeholder(..) + | Self::Union(..) => None, + } + } + + /// Indicates whether the represented type is a composite one. + /// + /// [Objects][`ObjectMeta`], [interfaces][`InterfaceMeta`] and [unions][`UnionMeta`] are + /// composite types. + pub fn is_composite(&self) -> bool { + matches!( + self, + Self::Interface(..) | Self::Object(..) | Self::Union(..) + ) + } + + /// Indicates whether the represented type can occur in leaf positions of queries. + /// + /// Only [enums][`EnumMeta`] and [scalars][`ScalarMeta`] are leaf types. + pub fn is_leaf(&self) -> bool { + matches!(self, Self::Enum(..) | Self::Scalar(..)) + } + + /// Indicates whether the represented type is abstract. + /// + /// Only [interfaces][`InterfaceMeta`] and [unions][`UnionMeta`] are abstract types. + pub fn is_abstract(&self) -> bool { + matches!(self, Self::Interface(..) | Self::Union(..)) + } + + /// Indicates whether the represented type can be used in input positions (e.g. arguments or + /// variables). + /// + /// Only [scalars][`ScalarMeta`], [enums][`EnumMeta`] and [input objects][`InputObjectMeta`] are + /// input types. + pub fn is_input(&self) -> bool { + matches!( + self, + Self::Enum(..) | Self::InputObject(..) | Self::Scalar(..) + ) + } + + /// Indicates whether the represented type is GraphQL built-in. + pub fn is_builtin(&self) -> bool { + if let Some(name) = self.name() { + // "used exclusively by GraphQL’s introspection system" + { + name.starts_with("__") || + // https://spec.graphql.org/October2021#sec-Scalars + name == "Boolean" || name == "String" || name == "Int" || name == "Float" || name == "ID" || + // Our custom empty markers + name == "_EmptyMutation" || name == "_EmptySubscription" + } + } else { + false + } + } + + pub(crate) fn fields<'s>(&self, schema: &'s SchemaType) -> Option>> { + schema + .lookup_type(&self.as_type()) + .and_then(|tpe| match tpe { + Self::Interface(i) => Some(i.fields.iter().collect()), + Self::Object(o) => Some(o.fields.iter().collect()), + Self::Union(u) => Some( + u.of_type_names + .iter() + .filter_map(|n| schema.concrete_type_by_name(n)) + .filter_map(|t| t.fields(schema)) + .flatten() + .collect(), + ), + Self::Enum(..) + | Self::InputObject(..) + | Self::List(..) + | Self::Nullable(..) + | Self::Placeholder(..) + | Self::Scalar(..) => None, + }) } } @@ -805,6 +827,6 @@ where T::Error: IntoFieldError, { T::from_input_value(v) - .map(drop) .map_err(T::Error::into_field_error) + .map(drop) } diff --git a/juniper/src/schema/model.rs b/juniper/src/schema/model.rs index 83c89c26f..1176e926d 100644 --- a/juniper/src/schema/model.rs +++ b/juniper/src/schema/model.rs @@ -1,5 +1,6 @@ -use std::{borrow::Cow, fmt}; +use std::fmt; +use arcstr::ArcStr; use fnv::FnvHashMap; #[cfg(feature = "schema-language")] use graphql_parser::schema::Document; @@ -19,7 +20,6 @@ use crate::{ /// and provides the predefined metadata fields. #[derive(Debug)] pub struct RootNode< - 'a, QueryT: GraphQLType, MutationT: GraphQLType, SubscriptionT: GraphQLType, @@ -40,64 +40,13 @@ pub struct RootNode< #[doc(hidden)] pub subscription_info: SubscriptionT::TypeInfo, #[doc(hidden)] - pub schema: SchemaType<'a, S>, + pub schema: SchemaType, #[doc(hidden)] pub introspection_disabled: bool, } -/// Metadata for a schema -#[derive(Debug)] -pub struct SchemaType<'a, S> { - pub(crate) description: Option>, - pub(crate) types: FnvHashMap>, - pub(crate) query_type_name: String, - pub(crate) mutation_type_name: Option, - pub(crate) subscription_type_name: Option, - directives: FnvHashMap>, -} - -impl Context for SchemaType<'_, S> {} - -#[derive(Clone)] -pub enum TypeType<'a, S: 'a> { - Concrete(&'a MetaType<'a, S>), - NonNull(Box>), - List(Box>, Option), -} - -#[derive(Debug)] -pub struct DirectiveType<'a, S> { - pub name: String, - pub description: Option, - pub locations: Vec, - pub arguments: Vec>, - pub is_repeatable: bool, -} - -#[derive(Clone, PartialEq, Eq, Debug, GraphQLEnum)] -#[graphql(name = "__DirectiveLocation", internal)] -pub enum DirectiveLocation { - Query, - Mutation, - Subscription, - Field, - Scalar, - #[graphql(name = "FRAGMENT_DEFINITION")] - FragmentDefinition, - #[graphql(name = "FIELD_DEFINITION")] - FieldDefinition, - #[graphql(name = "VARIABLE_DEFINITION")] - VariableDefinition, - #[graphql(name = "FRAGMENT_SPREAD")] - FragmentSpread, - #[graphql(name = "INLINE_FRAGMENT")] - InlineFragment, - #[graphql(name = "ENUM_VALUE")] - EnumValue, -} - impl - RootNode<'_, QueryT, MutationT, SubscriptionT, DefaultScalarValue> + RootNode where QueryT: GraphQLType, MutationT: GraphQLType, @@ -110,9 +59,9 @@ where } } -impl<'a, QueryT, MutationT, SubscriptionT, S> RootNode<'a, QueryT, MutationT, SubscriptionT, S> +impl RootNode where - S: ScalarValue + 'a, + S: ScalarValue, QueryT: GraphQLType, MutationT: GraphQLType, SubscriptionT: GraphQLType, @@ -128,12 +77,12 @@ where } } -impl<'a, S, QueryT, MutationT, SubscriptionT> RootNode<'a, QueryT, MutationT, SubscriptionT, S> +impl RootNode where QueryT: GraphQLType, MutationT: GraphQLType, SubscriptionT: GraphQLType, - S: ScalarValue + 'a, + S: ScalarValue, { /// Construct a new root node from query and mutation nodes, /// while also providing type info objects for the query and @@ -184,7 +133,7 @@ where /// } /// } /// - /// type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; + /// type Schema = RootNode; /// /// let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()) /// .disable_introspection(); @@ -247,7 +196,7 @@ where /// The order of the generated definitions in the returned [`Document`] is NOT stable and may change without any /// real schema changes. #[must_use] - pub fn as_document(&'a self) -> Document<'a, &'a str> { + pub fn as_document(&self) -> Document<'_, &str> { use crate::schema::translate::{ SchemaTranslator as _, graphql_parser::GraphQLParserTranslator, }; @@ -256,7 +205,20 @@ where } } -impl<'a, S> SchemaType<'a, S> { +/// Metadata for a schema +#[derive(Debug)] +pub struct SchemaType { + pub(crate) description: Option, + pub(crate) types: FnvHashMap>, + pub(crate) query_type_name: String, + pub(crate) mutation_type_name: Option, + pub(crate) subscription_type_name: Option, + directives: FnvHashMap>, +} + +impl Context for SchemaType {} + +impl SchemaType { /// Create a new schema. pub fn new( query_info: &QueryT::TypeInfo, @@ -264,7 +226,7 @@ impl<'a, S> SchemaType<'a, S> { subscription_info: &SubscriptionT::TypeInfo, ) -> Self where - S: ScalarValue + 'a, + S: ScalarValue, QueryT: GraphQLType, MutationT: GraphQLType, SubscriptionT: GraphQLType, @@ -272,40 +234,38 @@ impl<'a, S> SchemaType<'a, S> { let mut directives = FnvHashMap::default(); let mut registry = Registry::new(FnvHashMap::default()); - let query_type_name = registry + let query_type_name: Box = registry .get_type::(query_info) .innermost_name() - .to_owned(); - let mutation_type_name = registry + .into(); + let mutation_type_name: Box = registry .get_type::(mutation_info) .innermost_name() - .to_owned(); - let subscription_type_name = registry + .into(); + let subscription_type_name: Box = registry .get_type::(subscription_info) .innermost_name() - .to_owned(); + .into(); registry.get_type::>(&()); - directives.insert("skip".into(), DirectiveType::new_skip(&mut registry)); - directives.insert("include".into(), DirectiveType::new_include(&mut registry)); - directives.insert( - "deprecated".into(), - DirectiveType::new_deprecated(&mut registry), - ); - directives.insert( - "specifiedBy".into(), - DirectiveType::new_specified_by(&mut registry), - ); + let skip_directive = DirectiveType::new_skip(&mut registry); + let include_directive = DirectiveType::new_include(&mut registry); + let deprecated_directive = DirectiveType::new_deprecated(&mut registry); + let specified_by_directive = DirectiveType::new_specified_by(&mut registry); + directives.insert(skip_directive.name.clone(), skip_directive); + directives.insert(include_directive.name.clone(), include_directive); + directives.insert(deprecated_directive.name.clone(), deprecated_directive); + directives.insert(specified_by_directive.name.clone(), specified_by_directive); let mut meta_fields = vec![ - registry.field::>("__schema", &()), + registry.field::>(arcstr::literal!("__schema"), &()), registry - .field::>("__type", &()) - .argument(registry.arg::("name", &())), + .field::>(arcstr::literal!("__type"), &()) + .argument(registry.arg::(arcstr::literal!("name"), &())), ]; - if let Some(root_type) = registry.types.get_mut(&query_type_name) { + if let Some(root_type) = registry.types.get_mut(query_type_name.as_ref()) { if let MetaType::Object(ObjectMeta { ref mut fields, .. }) = *root_type { fields.append(&mut meta_fields); } else { @@ -323,14 +283,14 @@ impl<'a, S> SchemaType<'a, S> { SchemaType { description: None, types: registry.types, - query_type_name, - mutation_type_name: if &mutation_type_name != "_EmptyMutation" { - Some(mutation_type_name) + query_type_name: query_type_name.into(), + mutation_type_name: if mutation_type_name.as_ref() != "_EmptyMutation" { + Some(mutation_type_name.into()) } else { None }, - subscription_type_name: if &subscription_type_name != "_EmptySubscription" { - Some(subscription_type_name) + subscription_type_name: if subscription_type_name.as_ref() != "_EmptySubscription" { + Some(subscription_type_name.into()) } else { None }, @@ -339,31 +299,31 @@ impl<'a, S> SchemaType<'a, S> { } /// Add a description. - pub fn set_description(&mut self, description: impl Into>) { + pub fn set_description(&mut self, description: impl Into) { self.description = Some(description.into()); } /// Add a directive like `skip` or `include`. - pub fn add_directive(&mut self, directive: DirectiveType<'a, S>) { + pub fn add_directive(&mut self, directive: DirectiveType) { self.directives.insert(directive.name.clone(), directive); } /// Get a type by name. - pub fn type_by_name(&self, name: &str) -> Option> { - self.types.get(name).map(|t| TypeType::Concrete(t)) + pub fn type_by_name(&self, name: impl AsRef) -> Option> { + self.types.get(name.as_ref()).map(|t| TypeType::Concrete(t)) } /// Get a concrete type by name. - pub fn concrete_type_by_name(&self, name: &str) -> Option<&MetaType> { - self.types.get(name) + pub fn concrete_type_by_name(&self, name: impl AsRef) -> Option<&MetaType> { + self.types.get(name.as_ref()) } - pub(crate) fn lookup_type(&self, tpe: &Type) -> Option<&MetaType> { - match *tpe { - Type::NonNullNamed(ref name) | Type::Named(ref name) => { - self.concrete_type_by_name(name) + pub(crate) fn lookup_type(&self, tpe: &Type>) -> Option<&MetaType> { + match tpe { + Type::Named(name) | Type::NonNullNamed(name) => { + self.concrete_type_by_name(name.as_ref()) } - Type::List(ref inner, _) | Type::NonNullList(ref inner, _) => self.lookup_type(inner), + Type::List(inner, ..) | Type::NonNullList(inner, ..) => self.lookup_type(inner), } } @@ -371,7 +331,7 @@ impl<'a, S> SchemaType<'a, S> { pub fn query_type(&self) -> TypeType { TypeType::Concrete( self.types - .get(&self.query_type_name) + .get(self.query_type_name.as_str()) .expect("Query type does not exist in schema"), ) } @@ -379,7 +339,7 @@ impl<'a, S> SchemaType<'a, S> { /// Get the concrete query type from the schema. pub fn concrete_query_type(&self) -> &MetaType { self.types - .get(&self.query_type_name) + .get(self.query_type_name.as_str()) .expect("Query type does not exist in schema") } @@ -432,18 +392,22 @@ impl<'a, S> SchemaType<'a, S> { } /// Make a type. - pub fn make_type(&self, t: &Type) -> TypeType { - match *t { - Type::NonNullNamed(ref n) => TypeType::NonNull(Box::new( - self.type_by_name(n).expect("Type not found in schema"), - )), - Type::NonNullList(ref inner, expected_size) => TypeType::NonNull(Box::new( - TypeType::List(Box::new(self.make_type(inner)), expected_size), - )), - Type::Named(ref n) => self.type_by_name(n).expect("Type not found in schema"), - Type::List(ref inner, expected_size) => { - TypeType::List(Box::new(self.make_type(inner)), expected_size) + pub fn make_type(&self, ty: &Type>) -> TypeType { + match ty { + Type::List(inner, expected_size) => { + TypeType::List(Box::new(self.make_type(inner)), *expected_size) } + Type::Named(n) => self + .type_by_name(n.as_ref()) + .expect("Type not found in schema"), + Type::NonNullList(inner, expected_size) => TypeType::NonNull(Box::new(TypeType::List( + Box::new(self.make_type(inner)), + *expected_size, + ))), + Type::NonNullNamed(n) => TypeType::NonNull(Box::new( + self.type_by_name(n.as_ref()) + .expect("Type not found in schema"), + )), } } @@ -512,10 +476,10 @@ impl<'a, S> SchemaType<'a, S> { } /// If the type is a subtype of another type. - pub fn is_subtype<'b>(&self, sub_type: &Type<'b>, super_type: &Type<'b>) -> bool { - use crate::ast::Type::*; + pub fn is_subtype<'b>(&self, sub_type: &DynType<'b>, super_type: &DynType<'b>) -> bool { + use DynType::*; - if super_type == sub_type { + if super_type.equals(sub_type) { return true; } @@ -523,12 +487,12 @@ impl<'a, S> SchemaType<'a, S> { (&NonNullNamed(ref super_name), &NonNullNamed(ref sub_name)) | (&Named(ref super_name), &Named(ref sub_name)) | (&Named(ref super_name), &NonNullNamed(ref sub_name)) => { - self.is_named_subtype(sub_name, super_name) + self.is_named_subtype(sub_name.as_ref(), super_name.as_ref()) } - (&NonNullList(ref super_inner, _), &NonNullList(ref sub_inner, _)) - | (&List(ref super_inner, _), &List(ref sub_inner, _)) - | (&List(ref super_inner, _), &NonNullList(ref sub_inner, _)) => { - self.is_subtype(sub_inner, super_inner) + (&NonNullList(super_inner, _), &NonNullList(sub_inner, _)) + | (&List(super_inner, _), &List(sub_inner, _)) + | (&List(super_inner, _), &NonNullList(sub_inner, _)) => { + self.is_subtype(&sub_inner.as_dyn_type(), &super_inner.as_dyn_type()) } _ => false, } @@ -549,48 +513,70 @@ impl<'a, S> SchemaType<'a, S> { } } +#[derive(Clone)] +pub enum TypeType<'a, S: 'a> { + Concrete(&'a MetaType), + NonNull(Box>), + List(Box>, Option), +} + +impl fmt::Display for TypeType<'_, S> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Concrete(t) => f.write_str(t.name().unwrap()), + Self::List(i, _) => write!(f, "[{i}]"), + Self::NonNull(i) => write!(f, "{i}!"), + } + } +} + impl<'a, S> TypeType<'a, S> { - #[inline] pub fn to_concrete(&self) -> Option<&'a MetaType> { - match *self { - TypeType::Concrete(t) => Some(t), - _ => None, + match self { + Self::Concrete(t) => Some(t), + Self::List(..) | Self::NonNull(..) => None, } } - #[inline] pub fn innermost_concrete(&self) -> &'a MetaType { - match *self { - TypeType::Concrete(t) => t, - TypeType::NonNull(ref n) | TypeType::List(ref n, _) => n.innermost_concrete(), + match self { + Self::Concrete(t) => t, + Self::NonNull(n) | Self::List(n, ..) => n.innermost_concrete(), } } - #[inline] - pub fn list_contents(&self) -> Option<&TypeType<'a, S>> { - match *self { - TypeType::List(ref n, _) => Some(n), - TypeType::NonNull(ref n) => n.list_contents(), - _ => None, + pub fn list_contents(&self) -> Option<&Self> { + match self { + Self::List(n, ..) => Some(n), + Self::NonNull(n) => n.list_contents(), + Self::Concrete(..) => None, } } - #[inline] pub fn is_non_null(&self) -> bool { - matches!(*self, TypeType::NonNull(_)) + matches!(self, TypeType::NonNull(..)) } } -impl<'a, S> DirectiveType<'a, S> -where - S: ScalarValue + 'a, -{ +#[derive(Debug)] +pub struct DirectiveType { + pub name: ArcStr, + pub description: Option, + pub locations: Vec, + pub arguments: Vec>, + pub is_repeatable: bool, +} + +impl DirectiveType { pub fn new( - name: &str, + name: impl Into, locations: &[DirectiveLocation], - arguments: &[Argument<'a, S>], + arguments: &[Argument], is_repeatable: bool, - ) -> Self { + ) -> Self + where + S: Clone, + { Self { name: name.into(), description: None, @@ -600,73 +586,89 @@ where } } - fn new_skip(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S> + fn new_skip(registry: &mut Registry) -> Self where S: ScalarValue, { Self::new( - "skip", + arcstr::literal!("skip"), &[ DirectiveLocation::Field, DirectiveLocation::FragmentSpread, DirectiveLocation::InlineFragment, ], - &[registry.arg::("if", &())], + &[registry.arg::(arcstr::literal!("if"), &())], false, ) } - fn new_include(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S> + fn new_include(registry: &mut Registry) -> Self where S: ScalarValue, { Self::new( - "include", + arcstr::literal!("include"), &[ DirectiveLocation::Field, DirectiveLocation::FragmentSpread, DirectiveLocation::InlineFragment, ], - &[registry.arg::("if", &())], + &[registry.arg::(arcstr::literal!("if"), &())], false, ) } - fn new_deprecated(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S> + fn new_deprecated(registry: &mut Registry) -> Self where S: ScalarValue, { Self::new( - "deprecated", + arcstr::literal!("deprecated"), &[ DirectiveLocation::FieldDefinition, DirectiveLocation::EnumValue, ], - &[registry.arg::("reason", &())], + &[registry.arg::(arcstr::literal!("reason"), &())], false, ) } - fn new_specified_by(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S> + fn new_specified_by(registry: &mut Registry) -> Self where S: ScalarValue, { Self::new( - "specifiedBy", + arcstr::literal!("specifiedBy"), &[DirectiveLocation::Scalar], - &[registry.arg::("url", &())], + &[registry.arg::(arcstr::literal!("url"), &())], false, ) } - pub fn description(mut self, description: &str) -> DirectiveType<'a, S> { + pub fn description(mut self, description: impl Into) -> Self { self.description = Some(description.into()); self } } +#[derive(Clone, Debug, Eq, GraphQLEnum, PartialEq)] +#[graphql(name = "__DirectiveLocation", internal)] +pub enum DirectiveLocation { + Query, + Mutation, + Subscription, + Field, + Scalar, + FragmentDefinition, + FieldDefinition, + VariableDefinition, + FragmentSpread, + InlineFragment, + EnumValue, +} + impl fmt::Display for DirectiveLocation { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { Self::Query => "query", Self::Mutation => "mutation", @@ -683,16 +685,6 @@ impl fmt::Display for DirectiveLocation { } } -impl fmt::Display for TypeType<'_, S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Self::Concrete(t) => f.write_str(t.name().unwrap()), - Self::List(i, _) => write!(f, "[{i}]"), - Self::NonNull(i) => write!(f, "{i}!"), - } - } -} - /// Sorts the provided [`TypeType`]s in the "type-then-name" manner. fn sort_concrete_types(types: &mut [TypeType]) { types.sort_by(|a, b| { @@ -718,18 +710,18 @@ mod concrete_type_sort { /// Returns a [`TypeType`] sorting weight by its type. pub fn by_type(t: &TypeType) -> u8 { match t { - TypeType::Concrete(MetaType::Enum(_)) => 0, - TypeType::Concrete(MetaType::InputObject(_)) => 1, - TypeType::Concrete(MetaType::Interface(_)) => 2, - TypeType::Concrete(MetaType::Scalar(_)) => 3, - TypeType::Concrete(MetaType::Object(_)) => 4, - TypeType::Concrete(MetaType::Union(_)) => 5, + TypeType::Concrete(MetaType::Enum(..)) => 0, + TypeType::Concrete(MetaType::InputObject(..)) => 1, + TypeType::Concrete(MetaType::Interface(..)) => 2, + TypeType::Concrete(MetaType::Scalar(..)) => 3, + TypeType::Concrete(MetaType::Object(..)) => 4, + TypeType::Concrete(MetaType::Union(..)) => 5, // NOTE: The following types are not part of the introspected types. TypeType::Concrete( - MetaType::List(_) | MetaType::Nullable(_) | MetaType::Placeholder(_), + MetaType::List(..) | MetaType::Nullable(..) | MetaType::Placeholder(..), ) => 6, // NOTE: Other variants will not appear since we're only sorting concrete types. - TypeType::List(..) | TypeType::NonNull(_) => 7, + TypeType::List(..) | TypeType::NonNull(..) => 7, } } @@ -744,11 +736,91 @@ mod concrete_type_sort { TypeType::Concrete(MetaType::Union(meta)) => Some(&meta.name), TypeType::Concrete( // NOTE: The following types are not part of the introspected types. - MetaType::List(_) | MetaType::Nullable(_) | MetaType::Placeholder(_), + MetaType::List(..) | MetaType::Nullable(..) | MetaType::Placeholder(..), ) // NOTE: Other variants will not appear since we're only sorting concrete types. | TypeType::List(..) - | TypeType::NonNull(_) => None, + | TypeType::NonNull(..) => None, + } + } +} + +/// Allows seeing [`Type`] with different name/string representations +/// as the same type without allocation. +// TODO: Ideally this type should not exist, but the reason it currently does is that `Type` has a +// recursive design to allow arbitrary number of list wrappings. +// The list layout could instead be modelled as a modifier so that type becomes a tuple of +// (name, modifier). +// If `Type` is modelled like this it becomes easier to project it as a borrowed version of +// itself, i.e. [Type] vs [Type<&str>]. +#[derive(Clone, Copy, Debug)] +pub enum DynType<'a> { + Named(&'a str), + List(&'a dyn AsDynType, Option), + NonNullNamed(&'a str), + NonNullList(&'a dyn AsDynType, Option), +} + +impl<'a> DynType<'a> { + pub fn equals(&self, other: &DynType) -> bool { + match (self, other) { + (Self::Named(n0), DynType::Named(n1)) => n0 == n1, + (Self::List(t0, s0), DynType::List(t1, s1)) => { + t0.as_dyn_type().equals(&t1.as_dyn_type()) && s0 == s1 + } + (Self::NonNullNamed(n0), DynType::NonNullNamed(n1)) => n0 == n1, + (Self::NonNullList(t0, s0), DynType::NonNullList(t1, s1)) => { + t0.as_dyn_type().equals(&t1.as_dyn_type()) && s0 == s1 + } + _ => false, + } + } + + pub fn innermost_name(&self) -> &'a str { + match self { + Self::Named(n) | Self::NonNullNamed(n) => n, + Self::List(l, _) | Self::NonNullList(l, _) => l.as_dyn_type().innermost_name(), + } + } +} + +impl fmt::Display for DynType<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Named(n) => write!(f, "{n}"), + Self::NonNullNamed(n) => write!(f, "{n}!"), + Self::List(t, _) => write!(f, "[{}]", t.as_dyn_type()), + Self::NonNullList(t, _) => write!(f, "[{}]!", t.as_dyn_type()), + } + } +} + +/// Conversion of a [`Type`] into a [`DynType`]. +pub trait AsDynType: fmt::Debug { + /// Project this value as a [`DynType`]. + /// + /// Should not allocate memory. + fn as_dyn_type(&self) -> DynType<'_>; +} + +impl AsDynType for Type { + fn as_dyn_type(&self) -> DynType<'_> { + match self { + Self::Named(n) => DynType::Named(n.as_str()), + Self::List(t, s) => DynType::List(t.as_ref(), *s), + Self::NonNullNamed(n) => DynType::NonNullNamed(n.as_str()), + Self::NonNullList(t, s) => DynType::NonNullList(t.as_ref(), *s), + } + } +} + +impl AsDynType for Type<&str> { + fn as_dyn_type(&self) -> DynType<'_> { + match self { + Self::Named(n) => DynType::Named(n), + Self::List(t, s) => DynType::List(t.as_ref(), *s), + Self::NonNullNamed(n) => DynType::NonNullNamed(n), + Self::NonNullList(t, s) => DynType::NonNullList(t.as_ref(), *s), } } } diff --git a/juniper/src/schema/schema.rs b/juniper/src/schema/schema.rs index f959391e0..c74694f97 100644 --- a/juniper/src/schema/schema.rs +++ b/juniper/src/schema/schema.rs @@ -1,3 +1,5 @@ +use arcstr::ArcStr; + use crate::{ ast::Selection, executor::{ExecutionResult, Executor, Registry}, @@ -18,27 +20,24 @@ use crate::schema::{ }; impl GraphQLType - for RootNode<'_, QueryT, MutationT, SubscriptionT, S> + for RootNode where S: ScalarValue, QueryT: GraphQLType, MutationT: GraphQLType, SubscriptionT: GraphQLType, { - fn name(info: &Self::TypeInfo) -> Option<&str> { + fn name(info: &Self::TypeInfo) -> Option { QueryT::name(info) } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { QueryT::meta(info, registry) } } impl GraphQLValue - for RootNode<'_, QueryT, MutationT, SubscriptionT, S> + for RootNode where S: ScalarValue, QueryT: GraphQLType, @@ -48,7 +47,7 @@ where type Context = QueryT::Context; type TypeInfo = QueryT::TypeInfo; - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { QueryT::name(info) } @@ -98,12 +97,12 @@ where } } -impl<'a, S, QueryT, MutationT, SubscriptionT> GraphQLValueAsync - for RootNode<'a, QueryT, MutationT, SubscriptionT, S> +impl GraphQLValueAsync + for RootNode where QueryT: GraphQLTypeAsync, QueryT::TypeInfo: Sync, - QueryT::Context: Sync + 'a, + QueryT::Context: Sync, MutationT: GraphQLTypeAsync, MutationT::TypeInfo: Sync, SubscriptionT: GraphQLType + Sync, @@ -117,11 +116,12 @@ where arguments: &'b Arguments, executor: &'b Executor, ) -> crate::BoxFuture<'b, ExecutionResult> { - use futures::future::ready; + use std::future; + match field_name { "__schema" | "__type" => { let v = self.resolve_field(info, field_name, arguments, executor); - Box::pin(ready(v)) + Box::pin(future::ready(v)) } _ => self .query_type @@ -130,15 +130,16 @@ where } } -#[graphql_object( +#[graphql_object] +#[graphql( name = "__Schema" - context = SchemaType<'a, S>, + context = SchemaType, scalar = S, internal, )] -impl<'a, S: ScalarValue + 'a> SchemaType<'a, S> { - fn description(&self) -> Option<&str> { - self.description.as_deref() +impl SchemaType { + fn description(&self) -> Option<&ArcStr> { + self.description.as_ref() } fn types(&self) -> Vec> { @@ -147,8 +148,8 @@ impl<'a, S: ScalarValue + 'a> SchemaType<'a, S> { .filter(|t| { t.to_concrete() .map(|t| { - !(t.name() == Some("_EmptyMutation") - || t.name() == Some("_EmptySubscription")) + !(t.name().map(ArcStr::as_str) == Some("_EmptyMutation") + || t.name().map(ArcStr::as_str) == Some("_EmptySubscription")) }) .unwrap_or(false) }) @@ -175,39 +176,40 @@ impl<'a, S: ScalarValue + 'a> SchemaType<'a, S> { } } -#[graphql_object( - name = "__Type" - context = SchemaType<'a, S>, +#[graphql_object] +#[graphql( + name = "__Type", + context = SchemaType, scalar = S, internal, )] impl<'a, S: ScalarValue + 'a> TypeType<'a, S> { - fn name(&self) -> Option<&str> { + fn name(&self) -> Option<&ArcStr> { match self { - TypeType::Concrete(t) => t.name(), - _ => None, + Self::Concrete(t) => t.name(), + Self::List(..) | Self::NonNull(..) => None, } } - fn description(&self) -> Option<&str> { + fn description(&self) -> Option<&ArcStr> { match self { - TypeType::Concrete(t) => t.description(), - _ => None, + Self::Concrete(t) => t.description(), + Self::List(..) | Self::NonNull(..) => None, } } - fn specified_by_url(&self) -> Option<&str> { + fn specified_by_url(&self) -> Option<&ArcStr> { match self { Self::Concrete(t) => t.specified_by_url(), - Self::NonNull(_) | Self::List(..) => None, + Self::List(..) | Self::NonNull(..) => None, } } fn kind(&self) -> TypeKind { match self { - TypeType::Concrete(t) => t.type_kind(), - TypeType::List(..) => TypeKind::List, - TypeType::NonNull(_) => TypeKind::NonNull, + Self::Concrete(t) => t.type_kind(), + Self::List(..) => TypeKind::List, + Self::NonNull(..) => TypeKind::NonNull, } } @@ -216,95 +218,130 @@ impl<'a, S: ScalarValue + 'a> TypeType<'a, S> { #[graphql(default = false)] include_deprecated: Option, ) -> Option>> { match self { - TypeType::Concrete(MetaType::Interface(InterfaceMeta { fields, .. })) - | TypeType::Concrete(MetaType::Object(ObjectMeta { fields, .. })) => Some( - fields - .iter() - .filter(|f| { - include_deprecated.unwrap_or_default() - || !f.deprecation_status.is_deprecated() - }) - .filter(|f| !f.name.starts_with("__")) - .collect(), - ), - _ => None, + Self::Concrete(t) => match t { + MetaType::Interface(InterfaceMeta { fields, .. }) + | MetaType::Object(ObjectMeta { fields, .. }) => Some( + fields + .iter() + .filter(|f| { + include_deprecated.unwrap_or_default() + || !f.deprecation_status.is_deprecated() + }) + .filter(|f| !f.name.starts_with("__")) + .collect(), + ), + MetaType::Enum(..) + | MetaType::InputObject(..) + | MetaType::List(..) + | MetaType::Nullable(..) + | MetaType::Placeholder(..) + | MetaType::Scalar(..) + | MetaType::Union(..) => None, + }, + Self::List(..) | Self::NonNull(..) => None, } } - fn of_type(&self) -> Option<&TypeType> { + fn of_type(&self) -> Option<&Self> { match self { - TypeType::Concrete(_) => None, - TypeType::List(l, _) | TypeType::NonNull(l) => Some(&**l), + Self::Concrete(..) => None, + Self::List(l, _) | Self::NonNull(l) => Some(&**l), } } fn input_fields(&self) -> Option<&[Argument]> { match self { - TypeType::Concrete(MetaType::InputObject(InputObjectMeta { input_fields, .. })) => { - Some(input_fields.as_slice()) - } - _ => None, + Self::Concrete(t) => match t { + MetaType::InputObject(InputObjectMeta { input_fields, .. }) => { + Some(input_fields.as_slice()) + } + MetaType::Enum(..) + | MetaType::Interface(..) + | MetaType::List(..) + | MetaType::Nullable(..) + | MetaType::Object(..) + | MetaType::Placeholder(..) + | MetaType::Scalar(..) + | MetaType::Union(..) => None, + }, + Self::List(..) | Self::NonNull(..) => None, } } - fn interfaces<'s>(&self, context: &'s SchemaType<'a, S>) -> Option>> { + fn interfaces<'s>(&self, context: &'s SchemaType) -> Option>> { match self { - TypeType::Concrete( - MetaType::Object(ObjectMeta { + Self::Concrete(t) => match t { + MetaType::Interface(InterfaceMeta { interface_names, .. }) - | MetaType::Interface(InterfaceMeta { + | MetaType::Object(ObjectMeta { interface_names, .. - }), - ) => Some( - interface_names - .iter() - .filter_map(|n| context.type_by_name(n)) - .collect(), - ), - _ => None, + }) => Some( + interface_names + .iter() + .filter_map(|n| context.type_by_name(n)) + .collect(), + ), + MetaType::Enum(..) + | MetaType::InputObject(..) + | MetaType::List(..) + | MetaType::Nullable(..) + | MetaType::Placeholder(..) + | MetaType::Scalar(..) + | MetaType::Union(..) => None, + }, + Self::List(..) | Self::NonNull(..) => None, } } - fn possible_types<'s>(&self, context: &'s SchemaType<'a, S>) -> Option>> { + fn possible_types<'s>(&self, context: &'s SchemaType) -> Option>> { match self { - TypeType::Concrete(MetaType::Union(UnionMeta { of_type_names, .. })) => Some( - of_type_names - .iter() - .filter_map(|tn| context.type_by_name(tn)) - .collect(), - ), - TypeType::Concrete(MetaType::Interface(InterfaceMeta { - name: iface_name, .. - })) => { - let mut type_names = context - .types - .values() - .filter_map(|ct| { - if let MetaType::Object(ObjectMeta { - name, - interface_names, - .. - }) = ct - { - interface_names - .iter() - .any(|iname| iname == iface_name) - .then(|| name.as_ref()) - } else { - None - } - }) - .collect::>(); - type_names.sort(); - Some( - type_names - .into_iter() - .filter_map(|n| context.type_by_name(n)) + Self::Concrete(t) => match t { + MetaType::Interface(InterfaceMeta { + name: iface_name, .. + }) => { + let mut type_names = context + .types + .values() + .filter_map(|ct| { + if let MetaType::Object(ObjectMeta { + name, + interface_names, + .. + }) = ct + { + interface_names + .iter() + .any(|iname| iname == iface_name) + .then_some(name) + } else { + None + } + }) + .collect::>(); + type_names.sort(); + Some( + type_names + .into_iter() + .filter_map(|n| context.type_by_name(n)) + .collect(), + ) + } + MetaType::Union(UnionMeta { of_type_names, .. }) => Some( + of_type_names + .iter() + .filter_map(|tn| context.type_by_name(tn)) .collect(), - ) - } - _ => None, + ), + MetaType::Enum(..) + | MetaType::InputObject(..) + | MetaType::List(..) + | MetaType::Nullable(..) + | MetaType::Object(..) + | MetaType::Placeholder(..) + | MetaType::Scalar(..) => None, + }, + Self::List(..) | Self::NonNull(..) => None, } } @@ -313,34 +350,45 @@ impl<'a, S: ScalarValue + 'a> TypeType<'a, S> { #[graphql(default = false)] include_deprecated: Option, ) -> Option> { match self { - TypeType::Concrete(MetaType::Enum(EnumMeta { values, .. })) => Some( - values - .iter() - .filter(|f| { - include_deprecated.unwrap_or_default() - || !f.deprecation_status.is_deprecated() - }) - .collect(), - ), - _ => None, + Self::Concrete(t) => match t { + MetaType::Enum(EnumMeta { values, .. }) => Some( + values + .iter() + .filter(|f| { + include_deprecated.unwrap_or_default() + || !f.deprecation_status.is_deprecated() + }) + .collect(), + ), + MetaType::InputObject(..) + | MetaType::Interface(..) + | MetaType::List(..) + | MetaType::Nullable(..) + | MetaType::Object(..) + | MetaType::Placeholder(..) + | MetaType::Scalar(..) + | MetaType::Union(..) => None, + }, + Self::List(..) | Self::NonNull(..) => None, } } } -#[graphql_object( +#[graphql_object] +#[graphql( name = "__Field", - context = SchemaType<'a, S>, + context = SchemaType, scalar = S, internal, )] -impl<'a, S: ScalarValue + 'a> Field<'a, S> { - fn name(&self) -> String { - self.name.clone().into() +impl Field { + fn name(&self) -> &ArcStr { + &self.name } #[graphql(name = "description")] - fn description_(&self) -> Option<&str> { - self.description.as_deref() + fn description_(&self) -> Option<&ArcStr> { + self.description.as_ref() } fn args(&self) -> Vec<&Argument> { @@ -350,7 +398,7 @@ impl<'a, S: ScalarValue + 'a> Field<'a, S> { } #[graphql(name = "type")] - fn type_<'s>(&self, context: &'s SchemaType<'a, S>) -> TypeType<'s, S> { + fn type_<'s>(&self, context: &'s SchemaType) -> TypeType<'s, S> { context.make_type(&self.field_type) } @@ -358,29 +406,30 @@ impl<'a, S: ScalarValue + 'a> Field<'a, S> { self.deprecation_status.is_deprecated() } - fn deprecation_reason(&self) -> Option<&str> { + fn deprecation_reason(&self) -> Option<&ArcStr> { self.deprecation_status.reason() } } -#[graphql_object( +#[graphql_object] +#[graphql( name = "__InputValue", - context = SchemaType<'a, S>, + context = SchemaType, scalar = S, internal, )] -impl<'a, S: ScalarValue + 'a> Argument<'a, S> { - fn name(&self) -> &str { +impl Argument { + fn name(&self) -> &ArcStr { &self.name } #[graphql(name = "description")] - fn description_(&self) -> Option<&str> { - self.description.as_deref() + fn description_(&self) -> Option<&ArcStr> { + self.description.as_ref() } #[graphql(name = "type")] - fn type_<'s>(&self, context: &'s SchemaType<'a, S>) -> TypeType<'s, S> { + fn type_<'s>(&self, context: &'s SchemaType) -> TypeType<'s, S> { context.make_type(&self.arg_type) } @@ -390,40 +439,42 @@ impl<'a, S: ScalarValue + 'a> Argument<'a, S> { } } -#[graphql_object(name = "__EnumValue", internal)] +#[graphql_object] +#[graphql(name = "__EnumValue", internal)] impl EnumValue { - fn name(&self) -> &str { + fn name(&self) -> &ArcStr { &self.name } #[graphql(name = "description")] - fn description_(&self) -> Option<&str> { - self.description.as_deref() + fn description_(&self) -> Option<&ArcStr> { + self.description.as_ref() } fn is_deprecated(&self) -> bool { self.deprecation_status.is_deprecated() } - fn deprecation_reason(&self) -> Option<&str> { + fn deprecation_reason(&self) -> Option<&ArcStr> { self.deprecation_status.reason() } } -#[graphql_object( +#[graphql_object] +#[graphql( name = "__Directive", - context = SchemaType<'a, S>, + context = SchemaType, scalar = S, internal, )] -impl<'a, S: ScalarValue + 'a> DirectiveType<'a, S> { - fn name(&self) -> &str { +impl DirectiveType { + fn name(&self) -> &ArcStr { &self.name } #[graphql(name = "description")] - fn description_(&self) -> Option<&str> { - self.description.as_deref() + fn description_(&self) -> Option<&ArcStr> { + self.description.as_ref() } fn locations(&self) -> &[DirectiveLocation] { diff --git a/juniper/src/schema/translate/graphql_parser.rs b/juniper/src/schema/translate/graphql_parser.rs index 0bf8a589a..9ad12d553 100644 --- a/juniper/src/schema/translate/graphql_parser.rs +++ b/juniper/src/schema/translate/graphql_parser.rs @@ -30,12 +30,12 @@ mod for_minimal_versions_check_only { pub struct GraphQLParserTranslator; -impl<'a, S: 'a, T> From<&'a SchemaType<'a, S>> for Document<'a, T> +impl<'a, S: 'a, T> From<&'a SchemaType> for Document<'a, T> where S: ScalarValue, T: Text<'a> + Default, { - fn from(input: &'a SchemaType<'a, S>) -> Document<'a, T> { + fn from(input: &'a SchemaType) -> Document<'a, T> { GraphQLParserTranslator::translate_schema(input) } } @@ -88,7 +88,7 @@ impl GraphQLParserTranslator { { ExternalInputValue { position: Pos::default(), - description: input.description.as_ref().map(From::from), + description: input.description.as_deref().map(Into::into), name: From::from(input.name.as_str()), value_type: GraphQLParserTranslator::translate_type(&input.arg_type), default_value: input @@ -139,21 +139,21 @@ impl GraphQLParserTranslator { } } - fn translate_type<'a, T>(input: &'a Type<'a>) -> ExternalType<'a, T> + fn translate_type<'a, T>(input: &'a Type>) -> ExternalType<'a, T> where T: Text<'a>, { match input { - Type::Named(x) => ExternalType::NamedType(From::from(x.as_ref())), - Type::List(x, _) => { + Type::List(x, ..) => { ExternalType::ListType(GraphQLParserTranslator::translate_type(x).into()) } + Type::Named(x) => ExternalType::NamedType(From::from(x.as_ref())), + Type::NonNullList(x, ..) => ExternalType::NonNullType(Box::new( + ExternalType::ListType(Box::new(GraphQLParserTranslator::translate_type(x))), + )), Type::NonNullNamed(x) => { ExternalType::NonNullType(Box::new(ExternalType::NamedType(From::from(x.as_ref())))) } - Type::NonNullList(x, _) => ExternalType::NonNullType(Box::new(ExternalType::ListType( - Box::new(GraphQLParserTranslator::translate_type(x)), - ))), } } @@ -165,13 +165,13 @@ impl GraphQLParserTranslator { match input { MetaType::Scalar(x) => ExternalTypeDefinition::Scalar(ExternalScalarType { position: Pos::default(), - description: x.description.as_ref().map(From::from), + description: x.description.as_deref().map(Into::into), name: From::from(x.name.as_ref()), directives: vec![], }), MetaType::Enum(x) => ExternalTypeDefinition::Enum(ExternalEnum { position: Pos::default(), - description: x.description.as_ref().map(|s| From::from(s.as_str())), + description: x.description.as_deref().map(Into::into), name: From::from(x.name.as_ref()), directives: vec![], values: x @@ -182,7 +182,7 @@ impl GraphQLParserTranslator { }), MetaType::Union(x) => ExternalTypeDefinition::Union(ExternalUnionType { position: Pos::default(), - description: x.description.as_ref().map(|s| From::from(s.as_str())), + description: x.description.as_deref().map(Into::into), name: From::from(x.name.as_ref()), directives: vec![], types: x @@ -193,7 +193,7 @@ impl GraphQLParserTranslator { }), MetaType::Interface(x) => ExternalTypeDefinition::Interface(ExternalInterfaceType { position: Pos::default(), - description: x.description.as_ref().map(|s| From::from(s.as_str())), + description: x.description.as_deref().map(Into::into), name: From::from(x.name.as_ref()), implements_interfaces: x .interface_names @@ -211,7 +211,7 @@ impl GraphQLParserTranslator { MetaType::InputObject(x) => { ExternalTypeDefinition::InputObject(ExternalInputObjectType { position: Pos::default(), - description: x.description.as_ref().map(|s| From::from(s.as_str())), + description: x.description.as_deref().map(Into::into), name: From::from(x.name.as_ref()), directives: vec![], fields: x @@ -224,7 +224,7 @@ impl GraphQLParserTranslator { } MetaType::Object(x) => ExternalTypeDefinition::Object(ExternalObjectType { position: Pos::default(), - description: x.description.as_ref().map(|s| From::from(s.as_str())), + description: x.description.as_deref().map(Into::into), name: From::from(x.name.as_ref()), directives: vec![], fields: x @@ -250,7 +250,7 @@ impl GraphQLParserTranslator { ExternalEnumValue { position: Pos::default(), name: From::from(input.name.as_ref()), - description: input.description.as_ref().map(|s| From::from(s.as_str())), + description: input.description.as_deref().map(Into::into), directives: generate_directives(&input.deprecation_status), } } @@ -274,7 +274,7 @@ impl GraphQLParserTranslator { ExternalField { position: Pos::default(), name: From::from(input.name.as_str()), - description: input.description.as_ref().map(|s| From::from(s.as_str())), + description: input.description.as_deref().map(Into::into), directives: generate_directives(&input.deprecation_status), field_type: GraphQLParserTranslator::translate_type(&input.field_type), arguments, @@ -293,7 +293,12 @@ where name: "deprecated".into(), arguments: reason .as_ref() - .map(|rsn| vec![(From::from("reason"), ExternalValue::String(rsn.into()))]) + .map(|rsn| { + vec![( + From::from("reason"), + ExternalValue::String(rsn.as_str().into()), + )] + }) .unwrap_or_default(), }), } diff --git a/juniper/src/tests/subscriptions.rs b/juniper/src/tests/subscriptions.rs index 524a963fe..c51388b3a 100644 --- a/juniper/src/tests/subscriptions.rs +++ b/juniper/src/tests/subscriptions.rs @@ -29,8 +29,7 @@ impl MyQuery { } } -type Schema = - RootNode<'static, MyQuery, EmptyMutation, MySubscription, DefaultScalarValue>; +type Schema = RootNode, MySubscription, DefaultScalarValue>; fn run(f: impl Future) -> O { let rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/juniper/src/tests/type_info_tests.rs b/juniper/src/tests/type_info_tests.rs index 6b43a7efc..163803b50 100644 --- a/juniper/src/tests/type_info_tests.rs +++ b/juniper/src/tests/type_info_tests.rs @@ -1,3 +1,4 @@ +use arcstr::ArcStr; use indexmap::IndexMap; use crate::{ @@ -12,8 +13,8 @@ use crate::{ }; pub struct NodeTypeInfo { - name: String, - attribute_names: Vec, + name: ArcStr, + attribute_names: Vec, } pub struct Node { @@ -24,18 +25,15 @@ impl GraphQLType for Node where S: ScalarValue, { - fn name(info: &Self::TypeInfo) -> Option<&str> { - Some(&info.name) + fn name(info: &Self::TypeInfo) -> Option { + Some(info.name.clone()) } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { let fields = info .attribute_names .iter() - .map(|name| registry.field::(name, &())) + .map(|name| registry.field::(name.clone(), &())) .collect::>(); registry @@ -51,7 +49,7 @@ where type Context = (); type TypeInfo = NodeTypeInfo; - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option { >::name(info) } diff --git a/juniper/src/types/async_await.rs b/juniper/src/types/async_await.rs index 2595b34cd..e4c017ba8 100644 --- a/juniper/src/types/async_await.rs +++ b/juniper/src/types/async_await.rs @@ -203,8 +203,7 @@ where .concrete_type_by_name( instance .type_name(info) - .expect("Resolving named type's selection set") - .as_ref(), + .expect("Resolving named type's selection set"), ) .expect("Type not found in schema"); @@ -310,7 +309,7 @@ where if executor .schema() .is_named_subtype(&concrete_type_name, fragment.type_condition.item) - || Some(fragment.type_condition.item) == type_name + || Some(fragment.type_condition.item) == type_name.as_deref() { let sub_result = instance .resolve_into_type_async( diff --git a/juniper/src/types/base.rs b/juniper/src/types/base.rs index 5e5f668cf..b21071d48 100644 --- a/juniper/src/types/base.rs +++ b/juniper/src/types/base.rs @@ -1,3 +1,4 @@ +use arcstr::ArcStr; use indexmap::IndexMap; use crate::{ @@ -187,7 +188,7 @@ where /// any calculation and _always_ return the same value. /// /// Usually, it should just call a [`GraphQLType::name`] inside. - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str>; + fn type_name(&self, info: &Self::TypeInfo) -> Option; /// Resolves the value of a single field on this [`GraphQLValue`]. /// @@ -310,8 +311,8 @@ where /// ``` /// # use std::collections::HashMap; /// use juniper::{ -/// meta::MetaType, Arguments, Context, DefaultScalarValue, Executor, ExecutionResult, -/// FieldResult, GraphQLType, GraphQLValue, Registry, +/// arcstr, meta::MetaType, ArcStr, Arguments, Context, DefaultScalarValue, Executor, +/// ExecutionResult, FieldResult, GraphQLType, GraphQLValue, Registry, /// }; /// /// #[derive(Debug)] @@ -322,21 +323,19 @@ where /// struct User { id: String, name: String, friend_ids: Vec } /// /// impl GraphQLType for User { -/// fn name(_: &()) -> Option<&'static str> { -/// Some("User") +/// fn name(_: &()) -> Option { +/// Some(arcstr::literal!("User")) /// } /// -/// fn meta<'r>(_: &(), registry: &mut Registry<'r>) -> MetaType<'r> -/// where DefaultScalarValue: 'r, -/// { +/// fn meta(_: &(), registry: &mut Registry) -> MetaType { /// // First, we need to define all fields and their types on this type. /// // /// // If we need arguments, want to implement interfaces, or want to add documentation /// // strings, we can do it here. /// let fields = &[ -/// registry.field::<&String>("id", &()), -/// registry.field::<&String>("name", &()), -/// registry.field::>("friends", &()), +/// registry.field::(arcstr::literal!("id"), &()), +/// registry.field::(arcstr::literal!("name"), &()), +/// registry.field::>(arcstr::literal!("friends"), &()), /// ]; /// registry.build_object_type::(&(), fields).into_meta() /// } @@ -346,7 +345,7 @@ where /// type Context = Database; /// type TypeInfo = (); /// -/// fn type_name(&self, _: &()) -> Option<&'static str> { +/// fn type_name(&self, _: &()) -> Option { /// ::name(&()) /// } /// @@ -398,12 +397,10 @@ where /// /// This function will be called multiple times during schema construction. It must _not_ /// perform any calculation and _always_ return the same value. - fn name(info: &Self::TypeInfo) -> Option<&str>; + fn name(info: &Self::TypeInfo) -> Option; /// Returns [`MetaType`] representing this [`GraphQLType`]. - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r; + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType; } /// Resolver logic for queries'/mutations' selection set. @@ -428,8 +425,7 @@ where .concrete_type_by_name( instance .type_name(info) - .expect("Resolving named type's selection set") - .as_ref(), + .expect("Resolving named type's selection set"), ) .expect("Type not found in schema"); @@ -524,7 +520,7 @@ where if executor .schema() .is_named_subtype(&concrete_type_name, fragment.type_condition.item) - || Some(fragment.type_condition.item) == type_name + || Some(fragment.type_condition.item) == type_name.as_deref() { let sub_result = instance.resolve_into_type( info, diff --git a/juniper/src/types/containers.rs b/juniper/src/types/containers.rs index 31006970f..b72605ab4 100644 --- a/juniper/src/types/containers.rs +++ b/juniper/src/types/containers.rs @@ -3,6 +3,8 @@ use std::{ ptr, }; +use arcstr::ArcStr; + use crate::{ ast::{FromInputValue, InputValue, Selection, ToInputValue}, executor::{ExecutionResult, Executor, FieldError, IntoFieldError, Registry}, @@ -19,14 +21,11 @@ where T: GraphQLType, S: ScalarValue, { - fn name(_: &Self::TypeInfo) -> Option<&'static str> { + fn name(_: &Self::TypeInfo) -> Option { None } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { registry.build_nullable_type::(info).into_meta() } } @@ -39,7 +38,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> { + fn type_name(&self, _: &Self::TypeInfo) -> Option { None } @@ -105,14 +104,11 @@ where T: GraphQLType, S: ScalarValue, { - fn name(_: &Self::TypeInfo) -> Option<&'static str> { + fn name(_: &Self::TypeInfo) -> Option { None } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { registry.build_list_type::(info, None).into_meta() } } @@ -125,7 +121,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> { + fn type_name(&self, _: &Self::TypeInfo) -> Option { None } @@ -225,14 +221,11 @@ where S: ScalarValue, T: GraphQLType, { - fn name(_: &Self::TypeInfo) -> Option<&'static str> { + fn name(_: &Self::TypeInfo) -> Option { None } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { registry.build_list_type::(info, None).into_meta() } } @@ -245,7 +238,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> { + fn type_name(&self, _: &Self::TypeInfo) -> Option { None } @@ -292,14 +285,11 @@ where S: ScalarValue, T: GraphQLType, { - fn name(_: &Self::TypeInfo) -> Option<&'static str> { + fn name(_: &Self::TypeInfo) -> Option { None } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { registry.build_list_type::(info, Some(N)).into_meta() } } @@ -312,7 +302,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> { + fn type_name(&self, _: &Self::TypeInfo) -> Option { None } diff --git a/juniper/src/types/name.rs b/juniper/src/types/name.rs index 899137ad7..3173fffdb 100644 --- a/juniper/src/types/name.rs +++ b/juniper/src/types/name.rs @@ -1,14 +1,30 @@ -use std::{ - borrow::Borrow, - error::Error, - fmt::{Display, Formatter, Result as FmtResult}, - str::FromStr, -}; +use std::{borrow::Borrow, error::Error, fmt}; -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Name(String); +use arcstr::ArcStr; + +#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Name(ArcStr); impl Name { + /// Creates a new [`Name`] out of the provided `input` string, if it [`is_valid`]. + /// + /// [`is_valid`]: Name::is_valid + pub fn new(input: S) -> Result + where + S: AsRef + Into, + { + if Self::is_valid(input.as_ref()) { + Ok(Name(input.into())) + } else { + Err(NameParseError(arcstr::format!( + "`Name` must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{}\" does not", + input.as_ref(), + ))) + } + } + + /// Validates the provided `input` string to represent a valid [`Name`]. + #[must_use] pub fn is_valid(input: &str) -> bool { for (i, c) in input.chars().enumerate() { let is_valid = c.is_ascii_alphabetic() || c == '_' || (i > 0 && c.is_ascii_digit()); @@ -20,42 +36,29 @@ impl Name { } } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct NameParseError(String); - -impl Display for NameParseError { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - self.0.fmt(f) +impl Borrow for Name { + fn borrow(&self) -> &ArcStr { + &self.0 } } -impl Error for NameParseError { - fn description(&self) -> &str { +impl Borrow for Name { + fn borrow(&self) -> &str { &self.0 } } -impl FromStr for Name { - type Err = NameParseError; - fn from_str(s: &str) -> Result { - if Name::is_valid(s) { - Ok(Name(s.into())) - } else { - Err(NameParseError(format!( - "Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{s}\" does not", - ))) - } - } -} +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct NameParseError(ArcStr); -impl Borrow for Name { - fn borrow(&self) -> &String { - &self.0 +impl fmt::Display for NameParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) } } -impl Borrow for Name { - fn borrow(&self) -> &str { +impl Error for NameParseError { + fn description(&self) -> &str { &self.0 } } diff --git a/juniper/src/types/nullable.rs b/juniper/src/types/nullable.rs index 20f16708b..3c4b47895 100644 --- a/juniper/src/types/nullable.rs +++ b/juniper/src/types/nullable.rs @@ -1,3 +1,5 @@ +use arcstr::ArcStr; + use crate::{ ast::{FromInputValue, InputValue, Selection, ToInputValue}, executor::{ExecutionResult, Executor, Registry}, @@ -224,14 +226,11 @@ where T: GraphQLType, S: ScalarValue, { - fn name(_: &Self::TypeInfo) -> Option<&'static str> { + fn name(_: &Self::TypeInfo) -> Option { None } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { registry.build_nullable_type::(info).into_meta() } } @@ -244,7 +243,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name(&self, _: &Self::TypeInfo) -> Option<&'static str> { + fn type_name(&self, _: &Self::TypeInfo) -> Option { None } diff --git a/juniper/src/types/pointers.rs b/juniper/src/types/pointers.rs index f54495014..584f30dd2 100644 --- a/juniper/src/types/pointers.rs +++ b/juniper/src/types/pointers.rs @@ -1,5 +1,7 @@ use std::{fmt, sync::Arc}; +use arcstr::ArcStr; + use crate::{ BoxFuture, ast::{FromInputValue, InputValue, Selection, ToInputValue}, @@ -17,14 +19,11 @@ where T: GraphQLType + ?Sized, S: ScalarValue, { - fn name(info: &Self::TypeInfo) -> Option<&str> { + fn name(info: &Self::TypeInfo) -> Option { T::name(info) } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { T::meta(info, registry) } } @@ -37,7 +36,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { (**self).type_name(info) } @@ -115,14 +114,11 @@ where T: GraphQLType + ?Sized, S: ScalarValue, { - fn name(info: &Self::TypeInfo) -> Option<&str> { + fn name(info: &Self::TypeInfo) -> Option { T::name(info) } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { T::meta(info, registry) } } @@ -135,7 +131,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { (**self).type_name(info) } @@ -211,14 +207,11 @@ where S: ScalarValue, T: GraphQLType + ?Sized, { - fn name(info: &Self::TypeInfo) -> Option<&str> { + fn name(info: &Self::TypeInfo) -> Option { T::name(info) } - fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(info: &Self::TypeInfo, registry: &mut Registry) -> MetaType { T::meta(info, registry) } } @@ -231,7 +224,7 @@ where type Context = T::Context; type TypeInfo = T::TypeInfo; - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { (**self).type_name(info) } diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs index e6e79d590..78f40fe69 100644 --- a/juniper/src/types/scalars.rs +++ b/juniper/src/types/scalars.rs @@ -66,7 +66,8 @@ impl fmt::Display for ID { } } -#[graphql_scalar(with = impl_string_scalar)] +#[graphql_scalar] +#[graphql(with = impl_string_scalar)] type String = std::string::String; mod impl_string_scalar { @@ -186,6 +187,26 @@ where }) } +#[graphql_scalar] +#[graphql(name = "String", with = impl_arcstr_scalar, parse_token(String))] +type ArcStr = arcstr::ArcStr; + +mod impl_arcstr_scalar { + use crate::{InputValue, ScalarValue, Value}; + + use super::ArcStr; + + pub(super) fn to_output(v: &ArcStr) -> Value { + Value::scalar(v.to_string()) + } + + pub(super) fn from_input(v: &InputValue) -> Result { + v.as_string_value() + .map(Into::into) + .ok_or_else(|| format!("Expected `String`, found: {v}")) + } +} + impl reflect::WrappedType for str { const VALUE: reflect::WrappedValue = 1; } @@ -202,14 +223,11 @@ impl GraphQLType for str where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("String") + fn name(_: &()) -> Option { + Some(arcstr::literal!("String")) } - fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(_: &(), registry: &mut Registry) -> MetaType { registry.build_scalar_type::(&()).into_meta() } } @@ -221,7 +239,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { >::name(info) } @@ -259,7 +277,8 @@ where } } -#[graphql_scalar(with = impl_boolean_scalar)] +#[graphql_scalar] +#[graphql(with = impl_boolean_scalar)] type Boolean = bool; mod impl_boolean_scalar { @@ -281,7 +300,8 @@ mod impl_boolean_scalar { } } -#[graphql_scalar(with = impl_int_scalar)] +#[graphql_scalar] +#[graphql(with = impl_int_scalar)] type Int = i32; mod impl_int_scalar { @@ -307,7 +327,8 @@ mod impl_int_scalar { } } -#[graphql_scalar(with = impl_float_scalar)] +#[graphql_scalar] +#[graphql(with = impl_float_scalar)] type Float = f64; mod impl_float_scalar { @@ -359,14 +380,11 @@ impl GraphQLType for EmptyMutation where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("_EmptyMutation") + fn name(_: &()) -> Option { + Some(arcstr::literal!("_EmptyMutation")) } - fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(_: &(), registry: &mut Registry) -> MetaType { registry.build_object_type::(&(), &[]).into_meta() } } @@ -378,7 +396,7 @@ where type Context = T; type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { >::name(info) } } @@ -420,14 +438,11 @@ impl GraphQLType for EmptySubscription where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("_EmptySubscription") + fn name(_: &()) -> Option { + Some(arcstr::literal!("_EmptySubscription")) } - fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(_: &(), registry: &mut Registry) -> MetaType { registry.build_object_type::(&(), &[]).into_meta() } } @@ -439,7 +454,7 @@ where type Context = T; type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { >::name(info) } } diff --git a/juniper/src/types/subscriptions.rs b/juniper/src/types/subscriptions.rs index 7a3fcde65..c80d00d29 100644 --- a/juniper/src/types/subscriptions.rs +++ b/juniper/src/types/subscriptions.rs @@ -188,7 +188,7 @@ where 'res: 'f, { Box::pin(async move { - if self.type_name(info) == Some(type_name) { + if self.type_name(info).as_deref() == Some(type_name) { self.resolve_into_stream(info, executor).await } else { panic!("resolve_into_type_stream must be implemented"); @@ -274,8 +274,7 @@ where .concrete_type_by_name( instance .type_name(info) - .expect("Resolving named type's selection set") - .as_ref(), + .expect("Resolving named type's selection set"), ) .expect("Type not found in schema"); diff --git a/juniper/src/types/utilities.rs b/juniper/src/types/utilities.rs index 42106c540..0c224f48f 100644 --- a/juniper/src/types/utilities.rs +++ b/juniper/src/types/utilities.rs @@ -85,7 +85,7 @@ where } } -/// Validates the specified GraphQL literal and returns an error message if the it's invalid. +/// Validates the specified GraphQL literal and returns an error message if it's invalid. pub fn validate_literal_value( schema: &SchemaType, arg_type: &TypeType, @@ -155,12 +155,12 @@ where .iter() .filter_map(|f| { (f.arg_type.is_non_null() && f.default_value.is_none()) - .then_some(&f.name) + .then_some(f.name.as_str()) }) .collect::>(); let error_message = obj.iter().find_map(|(key, value)| { - remaining_required_fields.remove(&key.item); + remaining_required_fields.remove(key.item.as_str()); validate_object_field( schema, arg_type, @@ -179,7 +179,7 @@ where } else { let missing_fields = remaining_required_fields .into_iter() - .map(|s| format!("\"{}\"", &**s)) + .map(|s| format!("\"{s}\"")) .collect::>() .join(", "); Some(error::missing_fields(arg_type, missing_fields)) diff --git a/juniper/src/validation/context.rs b/juniper/src/validation/context.rs index f46af2f30..bb10ce2b6 100644 --- a/juniper/src/validation/context.rs +++ b/juniper/src/validation/context.rs @@ -3,7 +3,10 @@ use std::{ fmt::{self, Debug}, }; -use crate::ast::{Definition, Document, Type}; +use crate::{ + ast::{Definition, Document}, + schema::model::DynType, +}; use crate::schema::{meta::MetaType, model::SchemaType}; @@ -18,13 +21,13 @@ pub struct RuleError { #[doc(hidden)] pub struct ValidatorContext<'a, S: Debug + 'a> { - pub schema: &'a SchemaType<'a, S>, + pub schema: &'a SchemaType, errors: Vec, - type_stack: Vec>>, - type_literal_stack: Vec>>, - input_type_stack: Vec>>, - input_type_literal_stack: Vec>>, - parent_type_stack: Vec>>, + type_stack: Vec>>, + type_literal_stack: Vec>>, + input_type_stack: Vec>>, + input_type_literal_stack: Vec>>, + parent_type_stack: Vec>>, fragment_names: HashSet<&'a str>, } @@ -109,7 +112,7 @@ impl<'a, S: Debug> ValidatorContext<'a, S> { } #[doc(hidden)] - pub fn with_pushed_type(&mut self, t: Option<&Type<'a>>, f: F) -> R + pub fn with_pushed_type(&mut self, t: Option>, f: F) -> R where F: FnOnce(&mut ValidatorContext<'a, S>) -> R, { @@ -120,7 +123,7 @@ impl<'a, S: Debug> ValidatorContext<'a, S> { self.type_stack.push(None); } - self.type_literal_stack.push(t.cloned()); + self.type_literal_stack.push(t); let res = f(self); @@ -144,7 +147,7 @@ impl<'a, S: Debug> ValidatorContext<'a, S> { } #[doc(hidden)] - pub fn with_pushed_input_type(&mut self, t: Option<&Type<'a>>, f: F) -> R + pub fn with_pushed_input_type(&mut self, t: Option>, f: F) -> R where F: FnOnce(&mut ValidatorContext<'a, S>) -> R, { @@ -155,7 +158,7 @@ impl<'a, S: Debug> ValidatorContext<'a, S> { self.input_type_stack.push(None); } - self.input_type_literal_stack.push(t.cloned()); + self.input_type_literal_stack.push(t); let res = f(self); @@ -166,27 +169,27 @@ impl<'a, S: Debug> ValidatorContext<'a, S> { } #[doc(hidden)] - pub fn current_type(&self) -> Option<&'a MetaType<'a, S>> { + pub fn current_type(&self) -> Option<&'a MetaType> { *self.type_stack.last().unwrap_or(&None) } #[doc(hidden)] - pub fn current_type_literal(&self) -> Option<&Type<'a>> { + pub fn current_type_literal(&self) -> Option> { match self.type_literal_stack.last() { - Some(Some(t)) => Some(t), + Some(Some(t)) => Some(*t), _ => None, } } #[doc(hidden)] - pub fn parent_type(&self) -> Option<&'a MetaType<'a, S>> { + pub fn parent_type(&self) -> Option<&'a MetaType> { *self.parent_type_stack.last().unwrap_or(&None) } #[doc(hidden)] - pub fn current_input_type_literal(&self) -> Option<&Type<'a>> { + pub fn current_input_type_literal(&self) -> Option> { match self.input_type_literal_stack.last() { - Some(Some(t)) => Some(t), + Some(Some(t)) => Some(*t), _ => None, } } diff --git a/juniper/src/validation/rules/arguments_of_correct_type.rs b/juniper/src/validation/rules/arguments_of_correct_type.rs index fdcc1f8ca..2cef42325 100644 --- a/juniper/src/validation/rules/arguments_of_correct_type.rs +++ b/juniper/src/validation/rules/arguments_of_correct_type.rs @@ -10,7 +10,7 @@ use crate::{ }; pub struct ArgumentsOfCorrectType<'a, S: fmt::Debug + 'a> { - current_args: Option<&'a Vec>>, + current_args: Option<&'a Vec>>, } pub fn factory<'a, S: fmt::Debug>() -> ArgumentsOfCorrectType<'a, S> { diff --git a/juniper/src/validation/rules/fields_on_correct_type.rs b/juniper/src/validation/rules/fields_on_correct_type.rs index 7e3a4ea96..729245e8b 100644 --- a/juniper/src/validation/rules/fields_on_correct_type.rs +++ b/juniper/src/validation/rules/fields_on_correct_type.rs @@ -1,3 +1,5 @@ +use arcstr::ArcStr; + use crate::{ Operation, OperationType, Selection, ast::Field, @@ -46,7 +48,10 @@ where { if let Some(parent_type) = context.parent_type() { let field_name = &field.item.name; - let type_name = parent_type.name().unwrap_or(""); + let type_name = parent_type + .name() + .map(ArcStr::as_str) + .unwrap_or(""); if parent_type.field_by_name(field_name.item).is_none() { if let MetaType::Union(..) = *parent_type { diff --git a/juniper/src/validation/rules/fragments_on_composite_types.rs b/juniper/src/validation/rules/fragments_on_composite_types.rs index e0724daae..3f8ad2a7f 100644 --- a/juniper/src/validation/rules/fragments_on_composite_types.rs +++ b/juniper/src/validation/rules/fragments_on_composite_types.rs @@ -1,3 +1,5 @@ +use arcstr::ArcStr; + use crate::{ ast::{Fragment, InlineFragment}, parser::Spanning, @@ -23,7 +25,10 @@ where { if let Some(current_type) = context.current_type() { if !current_type.is_composite() { - let type_name = current_type.name().unwrap_or(""); + let type_name = current_type + .name() + .map(ArcStr::as_str) + .unwrap_or(""); let type_cond = &f.item.type_condition; context.report_error( @@ -46,7 +51,7 @@ where .current_type() .iter() .filter(|&t| !t.is_composite()) - .map(|t| t.name().unwrap_or("")) + .map(|t| t.name().map(ArcStr::as_str).unwrap_or("")) .next(); if let Some(name) = invalid_type_name { diff --git a/juniper/src/validation/rules/known_argument_names.rs b/juniper/src/validation/rules/known_argument_names.rs index 4dc68dd1f..7aecf42e3 100644 --- a/juniper/src/validation/rules/known_argument_names.rs +++ b/juniper/src/validation/rules/known_argument_names.rs @@ -14,7 +14,7 @@ enum ArgumentPosition<'a> { } pub struct KnownArgumentNames<'a, S: Debug + 'a> { - current_args: Option<(ArgumentPosition<'a>, &'a Vec>)>, + current_args: Option<(ArgumentPosition<'a>, &'a Vec>)>, } pub fn factory<'a, S: Debug>() -> KnownArgumentNames<'a, S> { diff --git a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs index bd43914bc..698f9fdc7 100644 --- a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs +++ b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs @@ -1,5 +1,7 @@ use std::{borrow::Borrow, cell::RefCell, collections::HashMap, fmt::Debug, hash::Hash}; +use arcstr::ArcStr; + use crate::{ ast::{Arguments, Definition, Document, Field, Fragment, FragmentSpread, Selection, Type}, parser::{SourcePosition, Spanning}, @@ -18,7 +20,7 @@ struct ConflictReason(String, ConflictReasonMessage); struct AstAndDef<'a, S: Debug + 'a>( Option<&'a str>, &'a Spanning>, - Option<&'a FieldType<'a, S>>, + Option<&'a FieldType>, ); type AstAndDefCollection<'a, S> = OrderedMap<&'a str, Vec>>; @@ -550,22 +552,26 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { )) } - fn is_type_conflict(ctx: &ValidatorContext<'a, S>, t1: &Type, t2: &Type) -> bool { + fn is_type_conflict + PartialEq>( + ctx: &ValidatorContext<'a, S>, + t1: &Type, + t2: &Type, + ) -> bool { match (t1, t2) { - (&Type::List(ref inner1, expected_size1), &Type::List(ref inner2, expected_size2)) + (Type::List(inner1, expected_size1), Type::List(inner2, expected_size2)) | ( - &Type::NonNullList(ref inner1, expected_size1), - &Type::NonNullList(ref inner2, expected_size2), + Type::NonNullList(inner1, expected_size1), + Type::NonNullList(inner2, expected_size2), ) => { if expected_size1 != expected_size2 { return false; } Self::is_type_conflict(ctx, inner1, inner2) } - (&Type::NonNullNamed(ref n1), &Type::NonNullNamed(ref n2)) - | (&Type::Named(ref n1), &Type::Named(ref n2)) => { - let ct1 = ctx.schema.concrete_type_by_name(n1); - let ct2 = ctx.schema.concrete_type_by_name(n2); + (Type::Named(n1), Type::Named(n2)) + | (Type::NonNullNamed(n1), Type::NonNullNamed(n2)) => { + let ct1 = ctx.schema.concrete_type_by_name(n1.as_ref()); + let ct2 = ctx.schema.concrete_type_by_name(n2.as_ref()); if ct1.map(MetaType::is_leaf).unwrap_or(false) || ct2.map(MetaType::is_leaf).unwrap_or(false) @@ -670,7 +676,7 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { } ast_and_defs.get_mut(response_name).unwrap().push(AstAndDef( - parent_type.and_then(MetaType::name), + parent_type.and_then(MetaType::name).map(ArcStr::as_str), f, field_def, )); @@ -757,6 +763,8 @@ fn format_reason(reason: &ConflictReasonMessage) -> String { #[cfg(test)] mod tests { + use arcstr::ArcStr; + use super::{ConflictReason, ConflictReasonMessage::*, error_message, factory}; use crate::{ @@ -1396,18 +1404,15 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("SomeBox") + fn name(_: &()) -> Option { + Some(arcstr::literal!("SomeBox")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ - registry.field::>("deepBox", i), - registry.field::>("unrelatedField", i), - registry.field::>("otherField", i), + registry.field::>(arcstr::literal!("deepBox"), i), + registry.field::>(arcstr::literal!("unrelatedField"), i), + registry.field::>(arcstr::literal!("otherField"), i), ]; registry.build_interface_type::(i, fields).into_meta() @@ -1421,7 +1426,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1430,21 +1435,19 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("StringBox") + fn name(_: &()) -> Option { + Some(arcstr::literal!("StringBox")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ - registry.field::>("scalar", i), - registry.field::>("deepBox", i), - registry.field::>("unrelatedField", i), - registry.field::>>>("listStringBox", i), - registry.field::>("stringBox", i), - registry.field::>("intBox", i), + registry.field::>(arcstr::literal!("scalar"), i), + registry.field::>(arcstr::literal!("deepBox"), i), + registry.field::>(arcstr::literal!("unrelatedField"), i), + registry + .field::>>>(arcstr::literal!("listStringBox"), i), + registry.field::>(arcstr::literal!("stringBox"), i), + registry.field::>(arcstr::literal!("intBox"), i), ]; registry @@ -1461,7 +1464,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1470,21 +1473,19 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("IntBox") + fn name(_: &()) -> Option { + Some(arcstr::literal!("IntBox")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ - registry.field::>("scalar", i), - registry.field::>("deepBox", i), - registry.field::>("unrelatedField", i), - registry.field::>>>("listStringBox", i), - registry.field::>("stringBox", i), - registry.field::>("intBox", i), + registry.field::>(arcstr::literal!("scalar"), i), + registry.field::>(arcstr::literal!("deepBox"), i), + registry.field::>(arcstr::literal!("unrelatedField"), i), + registry + .field::>>>(arcstr::literal!("listStringBox"), i), + registry.field::>(arcstr::literal!("stringBox"), i), + registry.field::>(arcstr::literal!("intBox"), i), ]; registry @@ -1501,7 +1502,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1510,15 +1511,12 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("NonNullStringBox1") + fn name(_: &()) -> Option { + Some(arcstr::literal!("NonNullStringBox1")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { - let fields = &[registry.field::("scalar", i)]; + fn meta(i: &(), registry: &mut Registry) -> MetaType { + let fields = &[registry.field::(arcstr::literal!("scalar"), i)]; registry.build_interface_type::(i, fields).into_meta() } @@ -1531,7 +1529,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1540,18 +1538,15 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("NonNullStringBox1Impl") + fn name(_: &()) -> Option { + Some(arcstr::literal!("NonNullStringBox1Impl")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ - registry.field::("scalar", i), - registry.field::>("deepBox", i), - registry.field::>("unrelatedField", i), + registry.field::(arcstr::literal!("scalar"), i), + registry.field::>(arcstr::literal!("deepBox"), i), + registry.field::>(arcstr::literal!("unrelatedField"), i), ]; registry @@ -1571,7 +1566,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1580,15 +1575,12 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("NonNullStringBox2") + fn name(_: &()) -> Option { + Some(arcstr::literal!("NonNullStringBox2")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { - let fields = &[registry.field::("scalar", i)]; + fn meta(i: &(), registry: &mut Registry) -> MetaType { + let fields = &[registry.field::(arcstr::literal!("scalar"), i)]; registry.build_interface_type::(i, fields).into_meta() } @@ -1601,7 +1593,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1610,18 +1602,15 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("NonNullStringBox2Impl") + fn name(_: &()) -> Option { + Some(arcstr::literal!("NonNullStringBox2Impl")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ - registry.field::("scalar", i), - registry.field::>("deepBox", i), - registry.field::>("unrelatedField", i), + registry.field::(arcstr::literal!("scalar"), i), + registry.field::>(arcstr::literal!("deepBox"), i), + registry.field::>(arcstr::literal!("unrelatedField"), i), ]; registry @@ -1641,7 +1630,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1650,17 +1639,14 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Node") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Node")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ - registry.field::>("id", i), - registry.field::>("name", i), + registry.field::>(arcstr::literal!("id"), i), + registry.field::>(arcstr::literal!("name"), i), ]; registry.build_object_type::(i, fields).into_meta() @@ -1674,7 +1660,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1683,15 +1669,12 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Edge") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Edge")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { - let fields = &[registry.field::>("node", i)]; + fn meta(i: &(), registry: &mut Registry) -> MetaType { + let fields = &[registry.field::>(arcstr::literal!("node"), i)]; registry.build_object_type::(i, fields).into_meta() } @@ -1704,7 +1687,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1713,15 +1696,13 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Connection") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Connection")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { - let fields = &[registry.field::>>>("edges", i)]; + fn meta(i: &(), registry: &mut Registry) -> MetaType { + let fields = + &[registry.field::>>>(arcstr::literal!("edges"), i)]; registry.build_object_type::(i, fields).into_meta() } @@ -1734,7 +1715,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -1743,22 +1724,19 @@ mod tests { where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("QueryRoot") + fn name(_: &()) -> Option { + Some(arcstr::literal!("QueryRoot")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { registry.get_type::(i); registry.get_type::(i); registry.get_type::(i); registry.get_type::(i); let fields = &[ - registry.field::>("someBox", i), - registry.field::>("connection", i), + registry.field::>(arcstr::literal!("someBox"), i), + registry.field::>(arcstr::literal!("connection"), i), ]; registry.build_object_type::(i, fields).into_meta() } @@ -1771,7 +1749,7 @@ mod tests { type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } diff --git a/juniper/src/validation/rules/possible_fragment_spreads.rs b/juniper/src/validation/rules/possible_fragment_spreads.rs index ca23255cc..248b40c83 100644 --- a/juniper/src/validation/rules/possible_fragment_spreads.rs +++ b/juniper/src/validation/rules/possible_fragment_spreads.rs @@ -1,4 +1,6 @@ -use std::fmt::Debug; +use std::{collections::HashMap, fmt::Debug}; + +use arcstr::ArcStr; use crate::{ ast::{Definition, Document, FragmentSpread, InlineFragment}, @@ -8,10 +10,9 @@ use crate::{ validation::{ValidatorContext, Visitor}, value::ScalarValue, }; -use std::collections::HashMap; pub struct PossibleFragmentSpreads<'a, S: Debug + 'a> { - fragment_types: HashMap<&'a str, &'a MetaType<'a, S>>, + fragment_types: HashMap<&'a str, &'a MetaType>, } pub fn factory<'a, S: Debug>() -> PossibleFragmentSpreads<'a, S> { @@ -67,8 +68,11 @@ where ctx.report_error( &error_message( None, - parent_type.name().unwrap_or(""), - frag_type.name().unwrap_or(""), + parent_type + .name() + .map(ArcStr::as_str) + .unwrap_or(""), + frag_type.name().map(ArcStr::as_str).unwrap_or(""), ), &[frag.span.start], ); @@ -106,8 +110,11 @@ where ctx.report_error( &error_message( Some(spread.item.name.item), - parent_type.name().unwrap_or(""), - frag_type.name().unwrap_or(""), + parent_type + .name() + .map(ArcStr::as_str) + .unwrap_or(""), + frag_type.name().map(ArcStr::as_str).unwrap_or(""), ), &[spread.span.start], ); diff --git a/juniper/src/validation/rules/variables_in_allowed_position.rs b/juniper/src/validation/rules/variables_in_allowed_position.rs index d80b3eeda..8bbed58d9 100644 --- a/juniper/src/validation/rules/variables_in_allowed_position.rs +++ b/juniper/src/validation/rules/variables_in_allowed_position.rs @@ -1,5 +1,4 @@ use std::{ - borrow::Cow, collections::{HashMap, HashSet}, fmt, }; @@ -8,6 +7,7 @@ use crate::{ Span, ast::{Document, Fragment, FragmentSpread, Operation, Type, VariableDefinition}, parser::Spanning, + schema::model::{AsDynType, DynType}, validation::{ValidatorContext, Visitor}, value::ScalarValue, }; @@ -29,7 +29,7 @@ pub fn factory<'a, S: fmt::Debug>() -> VariableInAllowedPosition<'a, S> { pub struct VariableInAllowedPosition<'a, S: fmt::Debug + 'a> { spreads: HashMap, HashSet<&'a str>>, - variable_usages: HashMap, Vec<(SpannedInput<'a, String>, Type<'a>)>>, + variable_usages: HashMap, Vec<(SpannedInput<'a, String>, DynType<'a>)>>, #[expect(clippy::type_complexity, reason = "readable enough")] variable_defs: HashMap, Vec<&'a (Spanning<&'a str>, VariableDefinition<'a, S>)>>, current_scope: Option>, @@ -88,11 +88,14 @@ impl<'a, S: fmt::Debug> VariableInAllowedPosition<'a, S> { (&Some(_), Type::List(inner, expected_size)) => { Type::NonNullList(inner.clone(), *expected_size) } - (&Some(_), Type::Named(inner)) => Type::NonNullNamed(Cow::Borrowed(inner)), - (_, t) => t.clone(), + (&Some(_), Type::Named(inner)) => Type::NonNullNamed(*inner), + (_, ty) => ty.clone(), }; - if !ctx.schema.is_subtype(&expected_type, var_type) { + if !ctx + .schema + .is_subtype(&expected_type.as_dyn_type(), var_type) + { ctx.report_error( &error_message(var_name.item, expected_type, var_type), &[var_def_name.span.start, var_name.span.start], @@ -169,7 +172,7 @@ where self.variable_usages .entry(scope.clone()) .or_default() - .push((var_name, input_type.clone())); + .push((var_name, input_type)); } } } diff --git a/juniper/src/validation/test_harness.rs b/juniper/src/validation/test_harness.rs index 577fe6c65..576df2090 100644 --- a/juniper/src/validation/test_harness.rs +++ b/juniper/src/validation/test_harness.rs @@ -1,5 +1,7 @@ use std::mem; +use arcstr::ArcStr; + use crate::{ FieldError, GraphQLInputObject, IntoFieldError, ast::{Document, FromInputValue, InputValue}, @@ -76,17 +78,14 @@ impl GraphQLType for Being where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Being") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Being")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[registry - .field::>("name", i) - .argument(registry.arg::>("surname", i))]; + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i))]; registry.build_interface_type::(i, fields).into_meta() } @@ -99,7 +98,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -108,17 +107,14 @@ impl GraphQLType for Pet where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Pet") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Pet")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[registry - .field::>("name", i) - .argument(registry.arg::>("surname", i))]; + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i))]; registry.build_interface_type::(i, fields).into_meta() } @@ -131,7 +127,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -140,17 +136,14 @@ impl GraphQLType for Canine where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Canine") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Canine")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[registry - .field::>("name", i) - .argument(registry.arg::>("surname", i))]; + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i))]; registry.build_interface_type::(i, fields).into_meta() } @@ -163,7 +156,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -172,17 +165,14 @@ impl GraphQLType for Unpopulated where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Unpopulated") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Unpopulated")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[registry - .field::>("name", i) - .argument(registry.arg::>("surname", i))]; + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i))]; registry .build_interface_type::(i, fields) @@ -198,7 +188,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -207,14 +197,11 @@ impl GraphQLType for DogCommand where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("DogCommand") + fn name(_: &()) -> Option { + Some(arcstr::literal!("DogCommand")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { registry .build_enum_type::( i, @@ -235,7 +222,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -260,31 +247,28 @@ impl GraphQLType for Dog where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Dog") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Dog")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ registry - .field::>("name", i) - .argument(registry.arg::>("surname", i)), - registry.field::>("nickname", i), - registry.field::>("barkVolume", i), - registry.field::>("barks", i), + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i)), + registry.field::>(arcstr::literal!("nickname"), i), + registry.field::>(arcstr::literal!("barkVolume"), i), + registry.field::>(arcstr::literal!("barks"), i), registry - .field::>("doesKnowCommand", i) - .argument(registry.arg::>("dogCommand", i)), + .field::>(arcstr::literal!("doesKnowCommand"), i) + .argument(registry.arg::>(arcstr::literal!("dogCommand"), i)), registry - .field::>("isHousetrained", i) - .argument(registry.arg_with_default("atOtherHomes", &true, i)), + .field::>(arcstr::literal!("isHousetrained"), i) + .argument(registry.arg_with_default(arcstr::literal!("atOtherHomes"), &true, i)), registry - .field::>("isAtLocation", i) - .argument(registry.arg::>("x", i)) - .argument(registry.arg::>("y", i)), + .field::>(arcstr::literal!("isAtLocation"), i) + .argument(registry.arg::>(arcstr::literal!("x"), i)) + .argument(registry.arg::>(arcstr::literal!("y"), i)), ]; registry @@ -305,7 +289,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -314,14 +298,11 @@ impl GraphQLType for FurColor where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("FurColor") + fn name(_: &()) -> Option { + Some(arcstr::literal!("FurColor")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { registry .build_enum_type::( i, @@ -343,7 +324,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -369,22 +350,19 @@ impl GraphQLType for Cat where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Cat") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Cat")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ registry - .field::>("name", i) - .argument(registry.arg::>("surname", i)), - registry.field::>("nickname", i), - registry.field::>("meows", i), - registry.field::>("meowVolume", i), - registry.field::>("furColor", i), + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i)), + registry.field::>(arcstr::literal!("nickname"), i), + registry.field::>(arcstr::literal!("meows"), i), + registry.field::>(arcstr::literal!("meowVolume"), i), + registry.field::>(arcstr::literal!("furColor"), i), ]; registry @@ -401,7 +379,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -410,14 +388,11 @@ impl GraphQLType for CatOrDog where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("CatOrDog") + fn name(_: &()) -> Option { + Some(arcstr::literal!("CatOrDog")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let types = &[registry.get_type::(i), registry.get_type::(i)]; registry.build_union_type::(i, types).into_meta() @@ -431,7 +406,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -440,15 +415,12 @@ impl GraphQLType for Intelligent where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Intelligent") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Intelligent")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { - let fields = &[registry.field::>("iq", i)]; + fn meta(i: &(), registry: &mut Registry) -> MetaType { + let fields = &[registry.field::>(arcstr::literal!("iq"), i)]; registry.build_interface_type::(i, fields).into_meta() } @@ -461,7 +433,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -470,21 +442,18 @@ impl GraphQLType for Human where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Human") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Human")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ registry - .field::>("name", i) - .argument(registry.arg::>("surname", i)), - registry.field::>>>("pets", i), - registry.field::>>("relatives", i), - registry.field::>("iq", i), + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i)), + registry.field::>>>(arcstr::literal!("pets"), i), + registry.field::>>(arcstr::literal!("relatives"), i), + registry.field::>(arcstr::literal!("iq"), i), ]; registry .build_object_type::(i, fields) @@ -503,7 +472,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -512,20 +481,17 @@ impl GraphQLType for Alien where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("Alien") + fn name(_: &()) -> Option { + Some(arcstr::literal!("Alien")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ registry - .field::>("name", i) - .argument(registry.arg::>("surname", i)), - registry.field::>("iq", i), - registry.field::>("numEyes", i), + .field::>(arcstr::literal!("name"), i) + .argument(registry.arg::>(arcstr::literal!("surname"), i)), + registry.field::>(arcstr::literal!("iq"), i), + registry.field::>(arcstr::literal!("numEyes"), i), ]; registry @@ -545,7 +511,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -554,14 +520,11 @@ impl GraphQLType for DogOrHuman where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("DogOrHuman") + fn name(_: &()) -> Option { + Some(arcstr::literal!("DogOrHuman")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let types = &[registry.get_type::(i), registry.get_type::(i)]; registry.build_union_type::(i, types).into_meta() @@ -575,7 +538,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -584,14 +547,11 @@ impl GraphQLType for HumanOrAlien where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("HumanOrAlien") + fn name(_: &()) -> Option { + Some(arcstr::literal!("HumanOrAlien")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let types = &[registry.get_type::(i), registry.get_type::(i)]; registry.build_union_type::(i, types).into_meta() @@ -605,7 +565,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -614,20 +574,17 @@ impl GraphQLType for ComplexInput where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("ComplexInput") + fn name(_: &()) -> Option { + Some(arcstr::literal!("ComplexInput")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ - registry.arg::("requiredField", i), - registry.arg::>("intField", i), - registry.arg::>("stringField", i), - registry.arg::>("booleanField", i), - registry.arg::>>>("stringListField", i), + registry.arg::(arcstr::literal!("requiredField"), i), + registry.arg::>(arcstr::literal!("intField"), i), + registry.arg::>(arcstr::literal!("stringField"), i), + registry.arg::>(arcstr::literal!("booleanField"), i), + registry.arg::>>>(arcstr::literal!("stringListField"), i), ]; registry @@ -643,7 +600,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -691,59 +648,59 @@ impl GraphQLType for ComplicatedArgs where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("ComplicatedArgs") + fn name(_: &()) -> Option { + Some(arcstr::literal!("ComplicatedArgs")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ registry - .field::>("intArgField", i) - .argument(registry.arg::>("intArg", i)), + .field::>(arcstr::literal!("intArgField"), i) + .argument(registry.arg::>(arcstr::literal!("intArg"), i)), registry - .field::>("nonNullIntArgField", i) - .argument(registry.arg::("nonNullIntArg", i)), + .field::>(arcstr::literal!("nonNullIntArgField"), i) + .argument(registry.arg::(arcstr::literal!("nonNullIntArg"), i)), registry - .field::>("stringArgField", i) - .argument(registry.arg::>("stringArg", i)), + .field::>(arcstr::literal!("stringArgField"), i) + .argument(registry.arg::>(arcstr::literal!("stringArg"), i)), registry - .field::>("booleanArgField", i) - .argument(registry.arg::>("booleanArg", i)), + .field::>(arcstr::literal!("booleanArgField"), i) + .argument(registry.arg::>(arcstr::literal!("booleanArg"), i)), registry - .field::>("enumArgField", i) - .argument(registry.arg::>("enumArg", i)), + .field::>(arcstr::literal!("enumArgField"), i) + .argument(registry.arg::>(arcstr::literal!("enumArg"), i)), registry - .field::>("floatArgField", i) - .argument(registry.arg::>("floatArg", i)), + .field::>(arcstr::literal!("floatArgField"), i) + .argument(registry.arg::>(arcstr::literal!("floatArg"), i)), registry - .field::>("idArgField", i) - .argument(registry.arg::>("idArg", i)), + .field::>(arcstr::literal!("idArgField"), i) + .argument(registry.arg::>(arcstr::literal!("idArg"), i)), registry - .field::>("stringListArgField", i) - .argument(registry.arg::>>>("stringListArg", i)), + .field::>(arcstr::literal!("stringListArgField"), i) + .argument( + registry + .arg::>>>(arcstr::literal!("stringListArg"), i), + ), registry - .field::>("nonNullStringListArgField", i) - .argument(registry.arg::>("nonNullStringListArg", i)), + .field::>(arcstr::literal!("nonNullStringListArgField"), i) + .argument(registry.arg::>(arcstr::literal!("nonNullStringListArg"), i)), registry - .field::>("complexArgField", i) - .argument(registry.arg::>("complexArg", i)), + .field::>(arcstr::literal!("complexArgField"), i) + .argument(registry.arg::>(arcstr::literal!("complexArg"), i)), registry - .field::>("multipleReqs", i) - .argument(registry.arg::("req1", i)) - .argument(registry.arg::("req2", i)), + .field::>(arcstr::literal!("multipleReqs"), i) + .argument(registry.arg::(arcstr::literal!("req1"), i)) + .argument(registry.arg::(arcstr::literal!("req2"), i)), registry - .field::>("multipleOpts", i) - .argument(registry.arg_with_default("opt1", &0i32, i)) - .argument(registry.arg_with_default("opt2", &0i32, i)), + .field::>(arcstr::literal!("multipleOpts"), i) + .argument(registry.arg_with_default(arcstr::literal!("opt1"), &0i32, i)) + .argument(registry.arg_with_default(arcstr::literal!("opt2"), &0i32, i)), registry - .field::>("multipleOptAndReq", i) - .argument(registry.arg::("req1", i)) - .argument(registry.arg::("req2", i)) - .argument(registry.arg_with_default("opt1", &0i32, i)) - .argument(registry.arg_with_default("opt2", &0i32, i)), + .field::>(arcstr::literal!("multipleOptAndReq"), i) + .argument(registry.arg::(arcstr::literal!("req1"), i)) + .argument(registry.arg::(arcstr::literal!("req2"), i)) + .argument(registry.arg_with_default(arcstr::literal!("opt1"), &0i32, i)) + .argument(registry.arg_with_default(arcstr::literal!("opt2"), &0i32, i)), ]; registry.build_object_type::(i, fields).into_meta() @@ -757,7 +714,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -766,26 +723,23 @@ impl GraphQLType for QueryRoot where S: ScalarValue, { - fn name(_: &()) -> Option<&'static str> { - Some("QueryRoot") + fn name(_: &()) -> Option { + Some(arcstr::literal!("QueryRoot")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = &[ registry - .field::>("human", i) - .argument(registry.arg::>("id", i)), - registry.field::>("alien", i), - registry.field::>("dog", i), - registry.field::>("cat", i), - registry.field::>("pet", i), - registry.field::>("catOrDog", i), - registry.field::>("dorOrHuman", i), - registry.field::>("humanOrAlien", i), - registry.field::>("complicatedArgs", i), + .field::>(arcstr::literal!("human"), i) + .argument(registry.arg::>(arcstr::literal!("id"), i)), + registry.field::>(arcstr::literal!("alien"), i), + registry.field::>(arcstr::literal!("dog"), i), + registry.field::>(arcstr::literal!("cat"), i), + registry.field::>(arcstr::literal!("pet"), i), + registry.field::>(arcstr::literal!("catOrDog"), i), + registry.field::>(arcstr::literal!("dorOrHuman"), i), + registry.field::>(arcstr::literal!("humanOrAlien"), i), + registry.field::>(arcstr::literal!("complicatedArgs"), i), ]; registry.build_object_type::(i, fields).into_meta() @@ -799,7 +753,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -808,26 +762,23 @@ impl GraphQLType for MutationRoot where S: ScalarValue, { - fn name(_: &()) -> Option<&str> { - Some("MutationRoot") + fn name(_: &()) -> Option { + Some(arcstr::literal!("MutationRoot")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let _ = registry.get_type::(i); - let fields = [registry.field::("testInput", i).argument( - registry.arg_with_default::( - "input", + let fields = [registry + .field::(arcstr::literal!("testInput"), i) + .argument(registry.arg_with_default::( + arcstr::literal!("input"), &TestInput { id: 423, name: String::from("foo"), }, i, - ), - )]; + ))]; registry.build_object_type::(i, &fields).into_meta() } @@ -840,7 +791,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } @@ -849,14 +800,11 @@ impl GraphQLType for SubscriptionRoot where S: ScalarValue, { - fn name(_: &()) -> Option<&str> { - Some("SubscriptionRoot") + fn name(_: &()) -> Option { + Some(arcstr::literal!("SubscriptionRoot")) } - fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S> - where - S: 'r, - { + fn meta(i: &(), registry: &mut Registry) -> MetaType { let fields = []; registry.build_object_type::(i, &fields).into_meta() @@ -870,7 +818,7 @@ where type Context = (); type TypeInfo = (); - fn type_name<'i>(&self, info: &'i Self::TypeInfo) -> Option<&'i str> { + fn type_name(&self, info: &Self::TypeInfo) -> Option { ::name(info) } } diff --git a/juniper/src/validation/visitor.rs b/juniper/src/validation/visitor.rs index fbc75c7e6..839bdf293 100644 --- a/juniper/src/validation/visitor.rs +++ b/juniper/src/validation/visitor.rs @@ -1,12 +1,13 @@ -use std::borrow::Cow; - use crate::{ ast::{ Arguments, Definition, Directive, Document, Field, Fragment, FragmentSpread, - InlineFragment, InputValue, Operation, OperationType, Selection, Type, VariableDefinitions, + InlineFragment, InputValue, Operation, OperationType, Selection, VariableDefinitions, }, parser::Spanning, - schema::meta::Argument, + schema::{ + meta::Argument, + model::{AsDynType, DynType}, + }, validation::{ValidatorContext, Visitor, multi_visitor::MultiVisitorCons}, value::ScalarValue, }; @@ -39,7 +40,7 @@ where .. }, .. - }) => Some(Type::NonNullNamed(Cow::Borrowed(name))), + }) => Some(DynType::NonNullNamed(name)), Definition::Operation(Spanning { item: Operation { @@ -47,9 +48,9 @@ where .. }, .. - }) => Some(Type::NonNullNamed(Cow::Borrowed( + }) => Some(DynType::NonNullNamed( ctx.schema.concrete_query_type().name().unwrap(), - ))), + )), Definition::Operation(Spanning { item: Operation { @@ -60,7 +61,7 @@ where }) => ctx .schema .concrete_mutation_type() - .map(|t| Type::NonNullNamed(Cow::Borrowed(t.name().unwrap()))), + .map(|t| DynType::NonNullNamed(t.name().unwrap())), Definition::Operation(Spanning { item: Operation { @@ -71,10 +72,10 @@ where }) => ctx .schema .concrete_subscription_type() - .map(|t| Type::NonNullNamed(Cow::Borrowed(t.name().unwrap()))), + .map(|t| DynType::NonNullNamed(t.name().unwrap())), }; - ctx.with_pushed_type(def_type.as_ref(), |ctx| { + ctx.with_pushed_type(def_type, |ctx| { enter_definition(v, ctx, def); visit_definition(v, ctx, def); exit_definition(v, ctx, def); @@ -132,9 +133,9 @@ fn visit_variable_definitions<'a, S, V>( { if let Some(ref defs) = *defs { for def in defs.item.iter() { - let var_type = def.1.var_type.item.clone(); + let var_type = &def.1.var_type.item; - ctx.with_pushed_input_type(Some(&var_type), |ctx| { + ctx.with_pushed_input_type(Some(var_type.as_dyn_type()), |ctx| { v.enter_variable_definition(ctx, def); if let Some(ref default_value) = def.1.default_value { @@ -185,7 +186,7 @@ fn visit_directives<'a, S, V>( fn visit_arguments<'a, S, V>( v: &mut V, ctx: &mut ValidatorContext<'a, S>, - meta_args: Option<&Vec>>, + meta_args: Option<&'a Vec>>, arguments: &'a Option>>, ) where S: ScalarValue, @@ -195,7 +196,8 @@ fn visit_arguments<'a, S, V>( for argument in arguments.item.iter() { let arg_type = meta_args .and_then(|args| args.iter().find(|a| a.name == argument.0.item)) - .map(|a| &a.arg_type); + .map(|a| &a.arg_type) + .map(|t| t.as_dyn_type()); ctx.with_pushed_input_type(arg_type, |ctx| { v.enter_argument(ctx, argument); @@ -254,7 +256,7 @@ fn visit_field<'a, S, V>( .parent_type() .and_then(|t| t.field_by_name(field.item.name.item)); - let field_type = meta_field.map(|f| &f.field_type); + let field_type = meta_field.map(|f| f.field_type.as_dyn_type()); let field_args = meta_field.and_then(|f| f.arguments.as_ref()); ctx.with_pushed_type(field_type, |ctx| { @@ -307,10 +309,7 @@ fn visit_inline_fragment<'a, S, V>( item: type_name, .. }) = fragment.item.type_condition { - ctx.with_pushed_type( - Some(&Type::NonNullNamed(Cow::Borrowed(type_name))), - visit_fn, - ); + ctx.with_pushed_type(Some(DynType::NonNullNamed(type_name)), visit_fn); } else { visit_fn(ctx); } @@ -331,14 +330,15 @@ fn visit_input_value<'a, S, V>( for (key, value) in fields { let inner_type = ctx .current_input_type_literal() - .and_then(|t| match *t { - Type::NonNullNamed(ref name) | Type::Named(ref name) => { + .and_then(|t| match t { + DynType::NonNullNamed(name) | DynType::Named(name) => { ctx.schema.concrete_type_by_name(name) } _ => None, }) .and_then(|ct| ct.input_field_by_name(&key.item)) - .map(|f| &f.arg_type); + .map(|f| &f.arg_type) + .map(|t| t.as_dyn_type()); ctx.with_pushed_input_type(inner_type, |ctx| { v.enter_object_field(ctx, (key.as_ref(), value.as_ref())); @@ -348,14 +348,14 @@ fn visit_input_value<'a, S, V>( } } InputValue::List(ref ls) => { - let inner_type = ctx.current_input_type_literal().and_then(|t| match *t { - Type::List(ref inner, _) | Type::NonNullList(ref inner, _) => { - Some(inner.as_ref().clone()) + let inner_type = ctx.current_input_type_literal().and_then(|t| match t { + DynType::List(inner, _) | DynType::NonNullList(inner, _) => { + Some(inner.as_dyn_type()) } _ => None, }); - ctx.with_pushed_input_type(inner_type.as_ref(), |ctx| { + ctx.with_pushed_input_type(inner_type, |ctx| { for value in ls { visit_input_value(v, ctx, value); } diff --git a/juniper_actix/examples/subscription.rs b/juniper_actix/examples/subscription.rs index b99de8916..cad2a9045 100644 --- a/juniper_actix/examples/subscription.rs +++ b/juniper_actix/examples/subscription.rs @@ -17,7 +17,7 @@ use juniper::{ use juniper_actix::{graphiql_handler, graphql_handler, playground_handler, subscriptions}; use juniper_graphql_ws::ConnectionConfig; -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode, Subscription>; fn schema() -> Schema { Schema::new(Query, EmptyMutation::::new(), Subscription) diff --git a/juniper_actix/src/lib.rs b/juniper_actix/src/lib.rs index 92e4f3f0a..09bef1880 100644 --- a/juniper_actix/src/lib.rs +++ b/juniper_actix/src/lib.rs @@ -41,7 +41,7 @@ where /// Actix Web GraphQL Handler for GET and POST requests pub async fn graphql_handler( - schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>, + schema: &juniper::RootNode, context: &CtxT, req: HttpRequest, payload: actix_web::web::Payload, @@ -64,7 +64,7 @@ where } /// Actix GraphQL Handler for GET requests pub async fn get_graphql_handler( - schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>, + schema: &juniper::RootNode, context: &CtxT, req: HttpRequest, ) -> Result @@ -93,7 +93,7 @@ where /// Actix GraphQL Handler for POST requests pub async fn post_graphql_handler( - schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>, + schema: &juniper::RootNode, context: &CtxT, req: HttpRequest, payload: actix_web::web::Payload, @@ -195,7 +195,7 @@ pub mod subscriptions { pub async fn ws_handler( req: HttpRequest, stream: web::Payload, - schema: Arc>, + schema: Arc>, init: I, ) -> Result where @@ -238,7 +238,7 @@ pub mod subscriptions { pub async fn graphql_ws_handler( req: HttpRequest, stream: web::Payload, - schema: Arc>, + schema: Arc>, init: I, ) -> Result where @@ -306,7 +306,7 @@ pub mod subscriptions { pub async fn graphql_transport_ws_handler( req: HttpRequest, stream: web::Payload, - schema: Arc>, + schema: Arc>, init: I, ) -> Result where @@ -454,15 +454,14 @@ mod tests { }; use futures::future; use juniper::{ - EmptyMutation, EmptySubscription, RootNode, + EmptyMutation, EmptySubscription, http::tests::{HttpIntegration, TestResponse, run_http_test_suite}, tests::fixtures::starwars::schema::{Database, Query}, }; use super::*; - type Schema = - juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; + type Schema = juniper::RootNode, EmptySubscription>; async fn take_response_body_string(resp: ServiceResponse) -> String { let mut body = resp.into_body(); @@ -572,7 +571,7 @@ mod tests { #[actix_web::rt::test] async fn graphql_post_works_json_post() { - let schema: Schema = RootNode::new( + let schema = Schema::new( Query, EmptyMutation::::new(), EmptySubscription::::new(), @@ -607,7 +606,7 @@ mod tests { #[actix_web::rt::test] async fn graphql_get_works() { - let schema: Schema = RootNode::new( + let schema = Schema::new( Query, EmptyMutation::::new(), EmptySubscription::::new(), @@ -641,11 +640,11 @@ mod tests { #[actix_web::rt::test] async fn batch_request_works() { use juniper::{ - EmptyMutation, EmptySubscription, RootNode, + EmptyMutation, EmptySubscription, tests::fixtures::starwars::schema::{Database, Query}, }; - let schema: Schema = RootNode::new( + let schema = Schema::new( Query, EmptyMutation::::new(), EmptySubscription::::new(), @@ -856,7 +855,7 @@ mod subscription_tests { } } - type Schema = juniper::RootNode<'static, Query, EmptyMutation, Subscription>; + type Schema = juniper::RootNode, Subscription>; fn subscription( proto: &'static str, diff --git a/juniper_axum/examples/custom.rs b/juniper_axum/examples/custom.rs index 3c139a362..2ab60562f 100644 --- a/juniper_axum/examples/custom.rs +++ b/juniper_axum/examples/custom.rs @@ -21,7 +21,7 @@ use juniper_axum::{ use juniper_graphql_ws::ConnectionConfig; use tokio::net::TcpListener; -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode, Subscription>; async fn homepage() -> Html<&'static str> { "

juniper_axum/custom example

\ diff --git a/juniper_axum/examples/simple.rs b/juniper_axum/examples/simple.rs index c0895e170..0f57d19a5 100644 --- a/juniper_axum/examples/simple.rs +++ b/juniper_axum/examples/simple.rs @@ -43,7 +43,7 @@ impl Subscription { } } -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode; async fn homepage() -> Html<&'static str> { "

juniper_axum/simple example

\ diff --git a/juniper_axum/src/extract.rs b/juniper_axum/src/extract.rs index fae67458e..593aa8f24 100644 --- a/juniper_axum/src/extract.rs +++ b/juniper_axum/src/extract.rs @@ -43,7 +43,7 @@ use serde::Deserialize; /// } /// } /// -/// type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +/// type Schema = RootNode, EmptySubscription>; /// /// let schema = Schema::new( /// Query, diff --git a/juniper_axum/src/lib.rs b/juniper_axum/src/lib.rs index 7c172b464..201c9e578 100644 --- a/juniper_axum/src/lib.rs +++ b/juniper_axum/src/lib.rs @@ -57,7 +57,7 @@ pub use self::subscriptions::{graphql_transport_ws, graphql_ws, ws}; /// } /// } /// -/// type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +/// type Schema = RootNode, EmptySubscription>; /// /// let schema = Schema::new( /// Query, diff --git a/juniper_axum/src/subscriptions.rs b/juniper_axum/src/subscriptions.rs index d4e02b71c..675e92011 100644 --- a/juniper_axum/src/subscriptions.rs +++ b/juniper_axum/src/subscriptions.rs @@ -47,7 +47,7 @@ use juniper_graphql_ws::{Init, Schema, graphql_transport_ws, graphql_ws}; /// use tokio::time::interval; /// use tokio_stream::wrappers::IntervalStream; /// -/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +/// type Schema = RootNode; /// /// #[derive(Clone, Copy, Debug)] /// pub struct Query; @@ -133,7 +133,7 @@ pub fn ws( /// use tokio::time::interval; /// use tokio_stream::wrappers::IntervalStream; /// -/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +/// type Schema = RootNode; /// /// #[derive(Clone, Copy, Debug)] /// pub struct Query; @@ -225,7 +225,7 @@ pub fn graphql_transport_ws( /// use tokio::time::interval; /// use tokio_stream::wrappers::IntervalStream; /// -/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +/// type Schema = RootNode; /// /// #[derive(Clone, Copy, Debug)] /// pub struct Query; @@ -317,7 +317,7 @@ pub fn graphql_ws( /// use tokio::time::interval; /// use tokio_stream::wrappers::IntervalStream; /// -/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +/// type Schema = RootNode; /// /// #[derive(Clone, Copy, Debug)] /// pub struct Query; @@ -419,7 +419,7 @@ where /// use tokio::time::interval; /// use tokio_stream::wrappers::IntervalStream; /// -/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +/// type Schema = RootNode; /// /// #[derive(Clone, Copy, Debug)] /// pub struct Query; @@ -550,7 +550,7 @@ where /// use tokio::time::interval; /// use tokio_stream::wrappers::IntervalStream; /// -/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +/// type Schema = RootNode; /// /// #[derive(Clone, Copy, Debug)] /// pub struct Query; diff --git a/juniper_axum/tests/http_test_suite.rs b/juniper_axum/tests/http_test_suite.rs index 05f55f72f..0a79e52c2 100644 --- a/juniper_axum/tests/http_test_suite.rs +++ b/juniper_axum/tests/http_test_suite.rs @@ -16,7 +16,7 @@ use juniper::{ use juniper_axum::{extract::JuniperRequest, response::JuniperResponse}; use tower_service::Service as _; -type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = RootNode, EmptySubscription>; struct TestApp(Router); diff --git a/juniper_axum/tests/ws_test_suite.rs b/juniper_axum/tests/ws_test_suite.rs index 1987077d8..e13298c0f 100644 --- a/juniper_axum/tests/ws_test_suite.rs +++ b/juniper_axum/tests/ws_test_suite.rs @@ -18,7 +18,7 @@ use tokio::{ }; use tokio_tungstenite::{MaybeTlsStream, WebSocketStream, connect_async, tungstenite::Message}; -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode, Subscription>; #[derive(Clone)] struct TestApp(Router); diff --git a/juniper_codegen/src/common/deprecation.rs b/juniper_codegen/src/common/deprecation.rs index 512ac511e..6fb9fa539 100644 --- a/juniper_codegen/src/common/deprecation.rs +++ b/juniper_codegen/src/common/deprecation.rs @@ -107,10 +107,10 @@ impl Directive { impl ToTokens for Directive { fn to_tokens(&self, into: &mut TokenStream) { - let reason = self - .reason - .as_ref() - .map_or_else(|| quote! { None }, |text| quote! { Some(#text) }); + let reason = self.reason.as_ref().map_or_else( + || quote! { <::juniper::ArcStr>::None }, + |text| quote! { Some(::juniper::arcstr::literal!(#text)) }, + ); quote! { .deprecated(::core::option::Option::#reason) } @@ -134,7 +134,8 @@ mod parse_from_deprecated_attr_test { .into_inner(); assert_eq!( quote! { #desc }.to_string(), - quote! { .deprecated(::core::option::Option::Some("foo")) }.to_string(), + quote! { .deprecated(::core::option::Option::Some(::juniper::arcstr::literal!("foo"))) } + .to_string(), ); } @@ -146,7 +147,7 @@ mod parse_from_deprecated_attr_test { .into_inner(); assert_eq!( quote! { #desc }.to_string(), - quote! { .deprecated(::core::option::Option::None) }.to_string(), + quote! { .deprecated(::core::option::Option::<::juniper::ArcStr>::None) }.to_string(), ); } diff --git a/juniper_codegen/src/common/description.rs b/juniper_codegen/src/common/description.rs index 853a8570e..dcb2c8da4 100644 --- a/juniper_codegen/src/common/description.rs +++ b/juniper_codegen/src/common/description.rs @@ -102,7 +102,7 @@ impl ToTokens for Description { let desc = &self.0; quote! { - .description(#desc) + .description(::juniper::arcstr::literal!(#desc)) } .to_tokens(into); } @@ -123,7 +123,7 @@ mod parse_from_doc_attrs_test { .into_inner(); assert_eq!( quote! { #desc }.to_string(), - quote! { .description("foo") }.to_string(), + quote! { .description(::juniper::arcstr::literal!("foo")) }.to_string(), ); } @@ -139,7 +139,7 @@ mod parse_from_doc_attrs_test { .into_inner(); assert_eq!( quote! { #desc }.to_string(), - quote! { .description("foo\n\nbar") }.to_string(), + quote! { .description(::juniper::arcstr::literal!("foo\n\nbar")) }.to_string(), ); } diff --git a/juniper_codegen/src/common/field/arg.rs b/juniper_codegen/src/common/field/arg.rs index 5d8bb09d0..733bc6ef4 100644 --- a/juniper_codegen/src/common/field/arg.rs +++ b/juniper_codegen/src/common/field/arg.rs @@ -303,10 +303,12 @@ impl OnMethod { let method = if let Some(val) = &arg.default { quote_spanned! { val.span() => - .arg_with_default::<#ty>(#name, &#val, info) + .arg_with_default::<#ty>(::juniper::arcstr::literal!(#name), &#val, info) } } else { - quote! { .arg::<#ty>(#name, info) } + quote! { + .arg::<#ty>(::juniper::arcstr::literal!(#name), info) + } }; Some(quote! { .argument(registry #method #description) }) diff --git a/juniper_codegen/src/common/field/mod.rs b/juniper_codegen/src/common/field/mod.rs index 281512cf1..bc87b2fb7 100644 --- a/juniper_codegen/src/common/field/mod.rs +++ b/juniper_codegen/src/common/field/mod.rs @@ -299,7 +299,8 @@ impl Definition { .flat_map(|args| args.iter().filter_map(MethodArgument::method_meta_tokens)); quote! { - registry.field_convert::<#ty, _, Self::Context>(#name, info) + registry + .field_convert::<#ty, _, Self::Context>(::juniper::arcstr::literal!(#name), info) #( #args )* #description #deprecated diff --git a/juniper_codegen/src/graphql_enum/mod.rs b/juniper_codegen/src/graphql_enum/mod.rs index 7d23122d1..2474f3a95 100644 --- a/juniper_codegen/src/graphql_enum/mod.rs +++ b/juniper_codegen/src/graphql_enum/mod.rs @@ -438,7 +438,7 @@ impl Definition { let v_deprecation = &v.deprecated; quote! { - ::juniper::meta::EnumValue::new(#v_name) + ::juniper::meta::EnumValue::new(::juniper::arcstr::literal!(#v_name)) #v_description #v_deprecation } @@ -450,18 +450,14 @@ impl Definition { for #ident #ty_generics #where_clause { - fn name( - _ : &Self::TypeInfo, - ) -> ::core::option::Option<&'static ::core::primitive::str> { - ::core::option::Option::Some(#name) + fn name(_ : &Self::TypeInfo) -> ::core::option::Option<::juniper::ArcStr> { + ::core::option::Option::Some(::juniper::arcstr::literal!(#name)) } - fn meta<'r>( + fn meta( info: &Self::TypeInfo, - registry: &mut ::juniper::Registry<'r, #scalar> - ) -> ::juniper::meta::MetaType<'r, #scalar> - where #scalar: 'r, - { + registry: &mut ::juniper::Registry<#scalar>, + ) -> ::juniper::meta::MetaType<#scalar> { let variants = [#( #variants_meta ),*]; registry.build_enum_type::<#ident #ty_generics>(info, &variants) @@ -513,10 +509,10 @@ impl Definition { type Context = #context; type TypeInfo = (); - fn type_name<'__i>( + fn type_name( &self, - info: &'__i Self::TypeInfo, - ) -> ::core::option::Option<&'__i ::core::primitive::str> { + info: &Self::TypeInfo, + ) -> ::core::option::Option<::juniper::ArcStr> { >::name(info) } diff --git a/juniper_codegen/src/graphql_input_object/mod.rs b/juniper_codegen/src/graphql_input_object/mod.rs index e76574921..036160342 100644 --- a/juniper_codegen/src/graphql_input_object/mod.rs +++ b/juniper_codegen/src/graphql_input_object/mod.rs @@ -463,9 +463,15 @@ impl Definition { (!f.ignored).then(|| { let arg = if let Some(default) = &f.default { - quote! { .arg_with_default::<#ty>(#name, &#default, info) } + quote! { + .arg_with_default::<#ty>( + ::juniper::arcstr::literal!(#name), &#default, info, + ) + } } else { - quote! { .arg::<#ty>(#name, info) } + quote! { + .arg::<#ty>(::juniper::arcstr::literal!(#name), info) + } }; let description = &f.description; @@ -479,19 +485,14 @@ impl Definition { for #ident #ty_generics #where_clause { - fn name( - _: &Self::TypeInfo, - ) -> ::core::option::Option<&'static ::core::primitive::str> { - ::core::option::Option::Some(#name) + fn name(_: &Self::TypeInfo) -> ::core::option::Option<::juniper::ArcStr> { + ::core::option::Option::Some(::juniper::arcstr::literal!(#name)) } - fn meta<'r>( + fn meta( info: &Self::TypeInfo, - registry: &mut ::juniper::Registry<'r, #scalar>, - ) -> ::juniper::meta::MetaType<'r, #scalar> - where - #scalar: 'r, - { + registry: &mut ::juniper::Registry<#scalar>, + ) -> ::juniper::meta::MetaType<#scalar> { let fields = [#( #fields ),*]; registry .build_input_object_type::<#ident #ty_generics>(info, &fields) @@ -526,10 +527,10 @@ impl Definition { type Context = #context; type TypeInfo = (); - fn type_name<'__i>( + fn type_name( &self, - info: &'__i Self::TypeInfo, - ) -> ::core::option::Option<&'__i ::core::primitive::str> { + info: &Self::TypeInfo, + ) -> ::core::option::Option<::juniper::ArcStr> { >::name(info) } } diff --git a/juniper_codegen/src/graphql_interface/mod.rs b/juniper_codegen/src/graphql_interface/mod.rs index f9e56de18..feafb3b53 100644 --- a/juniper_codegen/src/graphql_interface/mod.rs +++ b/juniper_codegen/src/graphql_interface/mod.rs @@ -717,18 +717,14 @@ impl Definition { for #ty #ty_generics #where_clause { - fn name( - _ : &Self::TypeInfo, - ) -> ::core::option::Option<&'static ::core::primitive::str> { - ::core::option::Option::Some(#name) + fn name(_ : &Self::TypeInfo) -> ::core::option::Option<::juniper::ArcStr> { + ::core::option::Option::Some(::juniper::arcstr::literal!(#name)) } - fn meta<'r>( + fn meta( info: &Self::TypeInfo, - registry: &mut ::juniper::Registry<'r, #scalar> - ) -> ::juniper::meta::MetaType<'r, #scalar> - where #scalar: 'r, - { + registry: &mut ::juniper::Registry<#scalar>, + ) -> ::juniper::meta::MetaType<#scalar> { // Ensure all implementer types are registered. #( let _ = registry.get_type::<#implemented_for>(info); )* @@ -788,10 +784,10 @@ impl Definition { type Context = #context; type TypeInfo = (); - fn type_name<'__i>( + fn type_name( &self, - info: &'__i Self::TypeInfo, - ) -> ::core::option::Option<&'__i ::core::primitive::str> { + info: &Self::TypeInfo, + ) -> ::core::option::Option<::juniper::ArcStr> { >::name(info) } diff --git a/juniper_codegen/src/graphql_object/mod.rs b/juniper_codegen/src/graphql_object/mod.rs index 9d2612d3b..f59047bb1 100644 --- a/juniper_codegen/src/graphql_object/mod.rs +++ b/juniper_codegen/src/graphql_object/mod.rs @@ -457,18 +457,14 @@ impl Definition { #[automatically_derived] impl #impl_generics ::juniper::GraphQLType<#scalar> for #ty #where_clause { - fn name( - _ : &Self::TypeInfo, - ) -> ::core::option::Option<&'static ::core::primitive::str> { - ::core::option::Option::Some(#name) + fn name(_ : &Self::TypeInfo) -> ::core::option::Option<::juniper::ArcStr> { + ::core::option::Option::Some(::juniper::arcstr::literal!(#name)) } - fn meta<'r>( + fn meta( info: &Self::TypeInfo, - registry: &mut ::juniper::Registry<'r, #scalar> - ) -> ::juniper::meta::MetaType<'r, #scalar> - where #scalar: 'r, - { + registry: &mut ::juniper::Registry<#scalar>, + ) -> ::juniper::meta::MetaType<#scalar> { let fields = [ #( #fields_meta, )* ]; @@ -785,10 +781,10 @@ impl Definition { type Context = #context; type TypeInfo = (); - fn type_name<'__i>( + fn type_name( &self, - info: &'__i Self::TypeInfo, - ) -> ::core::option::Option<&'__i ::core::primitive::str> { + info: &Self::TypeInfo, + ) -> ::core::option::Option<::juniper::ArcStr> { >::name(info) } diff --git a/juniper_codegen/src/graphql_scalar/mod.rs b/juniper_codegen/src/graphql_scalar/mod.rs index b1f90ef91..4338e1fad 100644 --- a/juniper_codegen/src/graphql_scalar/mod.rs +++ b/juniper_codegen/src/graphql_scalar/mod.rs @@ -363,7 +363,9 @@ impl Definition { let description = &self.description; let specified_by_url = self.specified_by_url.as_ref().map(|url| { let url_lit = url.as_str(); - quote! { .specified_by_url(#url_lit) } + quote! { + .specified_by_url(::juniper::arcstr::literal!(#url_lit)) + } }); let (ty, generics) = self.impl_self_and_generics(false); @@ -374,19 +376,14 @@ impl Definition { impl #impl_gens ::juniper::GraphQLType<#scalar> for #ty #where_clause { - fn name( - _: &Self::TypeInfo, - ) -> ::core::option::Option<&'static ::core::primitive::str> { - ::core::option::Option::Some(#name) + fn name(_: &Self::TypeInfo) -> ::core::option::Option<::juniper::ArcStr> { + ::core::option::Option::Some(::juniper::arcstr::literal!(#name)) } - fn meta<'r>( + fn meta( info: &Self::TypeInfo, - registry: &mut ::juniper::Registry<'r, #scalar>, - ) -> ::juniper::meta::MetaType<'r, #scalar> - where - #scalar: 'r, - { + registry: &mut ::juniper::Registry<#scalar>, + ) -> ::juniper::meta::MetaType<#scalar> { registry.build_scalar_type::(info) #description #specified_by_url @@ -417,10 +414,10 @@ impl Definition { type Context = (); type TypeInfo = (); - fn type_name<'i>( + fn type_name( &self, - info: &'i Self::TypeInfo, - ) -> ::core::option::Option<&'i ::core::primitive::str> { + info: &Self::TypeInfo, + ) -> ::core::option::Option<::juniper::ArcStr> { >::name(info) } diff --git a/juniper_codegen/src/graphql_subscription/mod.rs b/juniper_codegen/src/graphql_subscription/mod.rs index 8f2757ed5..80e3c6914 100644 --- a/juniper_codegen/src/graphql_subscription/mod.rs +++ b/juniper_codegen/src/graphql_subscription/mod.rs @@ -49,10 +49,10 @@ impl Definition { type Context = #context; type TypeInfo = (); - fn type_name<'__i>( + fn type_name( &self, - info: &'__i Self::TypeInfo, - ) -> ::core::option::Option<&'__i ::core::primitive::str> { + info: &Self::TypeInfo, + ) -> ::core::option::Option<::juniper::ArcStr> { >::name(info) } diff --git a/juniper_codegen/src/graphql_union/mod.rs b/juniper_codegen/src/graphql_union/mod.rs index 95385e2dc..4a046612e 100644 --- a/juniper_codegen/src/graphql_union/mod.rs +++ b/juniper_codegen/src/graphql_union/mod.rs @@ -473,18 +473,14 @@ impl Definition { #[automatically_derived] impl #impl_generics ::juniper::GraphQLType<#scalar> for #ty_full #where_clause { - fn name( - _ : &Self::TypeInfo, - ) -> ::core::option::Option<&'static ::core::primitive::str> { - ::core::option::Option::Some(#name) + fn name(_ : &Self::TypeInfo) -> ::core::option::Option<::juniper::ArcStr> { + ::core::option::Option::Some(::juniper::arcstr::literal!(#name)) } - fn meta<'r>( + fn meta( info: &Self::TypeInfo, - registry: &mut ::juniper::Registry<'r, #scalar> - ) -> ::juniper::meta::MetaType<'r, #scalar> - where #scalar: 'r, - { + registry: &mut ::juniper::Registry<#scalar>, + ) -> ::juniper::meta::MetaType<#scalar> { let types = [ #( registry.get_type::<#variant_tys>(info), )* ]; @@ -527,10 +523,10 @@ impl Definition { type Context = #context; type TypeInfo = (); - fn type_name<'__i>( + fn type_name( &self, - info: &'__i Self::TypeInfo, - ) -> ::core::option::Option<&'__i ::core::primitive::str> { + info: &Self::TypeInfo, + ) -> ::core::option::Option<::juniper::ArcStr> { >::name(info) } diff --git a/juniper_graphql_ws/src/graphql_transport_ws/mod.rs b/juniper_graphql_ws/src/graphql_transport_ws/mod.rs index b2737e794..c1da0a528 100644 --- a/juniper_graphql_ws/src/graphql_transport_ws/mod.rs +++ b/juniper_graphql_ws/src/graphql_transport_ws/mod.rs @@ -666,7 +666,7 @@ mod test { type ClientMessage = super::ClientMessage; type ServerMessage = super::ServerMessage; - fn new_test_schema() -> Arc, Subscription>> { + fn new_test_schema() -> Arc, Subscription>> { Arc::new(RootNode::new(Query, EmptyMutation::new(), Subscription)) } diff --git a/juniper_graphql_ws/src/graphql_ws/mod.rs b/juniper_graphql_ws/src/graphql_ws/mod.rs index 6c56192d9..59b3ce27b 100644 --- a/juniper_graphql_ws/src/graphql_ws/mod.rs +++ b/juniper_graphql_ws/src/graphql_ws/mod.rs @@ -602,7 +602,7 @@ mod test { type ClientMessage = super::ClientMessage; type ServerMessage = super::ServerMessage; - fn new_test_schema() -> Arc, Subscription>> { + fn new_test_schema() -> Arc, Subscription>> { Arc::new(RootNode::new(Query, EmptyMutation::new(), Subscription)) } diff --git a/juniper_graphql_ws/src/schema.rs b/juniper_graphql_ws/src/schema.rs index 43b7f94b4..20769faf5 100644 --- a/juniper_graphql_ws/src/schema.rs +++ b/juniper_graphql_ws/src/schema.rs @@ -41,7 +41,7 @@ pub trait Schema: Unpin + Clone + Send + Sync + 'static { /// Returns the root node for the schema. fn root_node( &self, - ) -> &RootNode<'static, Self::Query, Self::Mutation, Self::Subscription, Self::ScalarValue>; + ) -> &RootNode; } /// This exists as a work-around for this issue: https://github.com/rust-lang/rust/issues/64552 @@ -50,7 +50,7 @@ pub trait Schema: Unpin + Clone + Send + Sync + 'static { // TODO: Remove this once that issue is resolved. #[doc(hidden)] pub struct ArcSchema( - pub Arc>, + pub Arc>, ) where QueryT: GraphQLTypeAsync + Send + 'static, @@ -100,13 +100,13 @@ where type SubscriptionTypeInfo = SubscriptionT::TypeInfo; type Subscription = SubscriptionT; - fn root_node(&self) -> &RootNode<'static, QueryT, MutationT, SubscriptionT, S> { + fn root_node(&self) -> &RootNode { &self.0 } } impl Schema - for Arc> + for Arc> where QueryT: GraphQLTypeAsync + Send + 'static, QueryT::TypeInfo: Send + Sync, @@ -126,7 +126,7 @@ where type SubscriptionTypeInfo = SubscriptionT::TypeInfo; type Subscription = SubscriptionT; - fn root_node(&self) -> &RootNode<'static, QueryT, MutationT, SubscriptionT, S> { + fn root_node(&self) -> &RootNode { self } } diff --git a/juniper_hyper/src/lib.rs b/juniper_hyper/src/lib.rs index 2dbc660cf..5a63dbb66 100644 --- a/juniper_hyper/src/lib.rs +++ b/juniper_hyper/src/lib.rs @@ -19,7 +19,7 @@ use url::form_urlencoded; /// Executes synchronously the provided GraphQL [`Request`] against the provided `schema` in the /// provided `context`, returning the encoded [`Response`]. pub async fn graphql_sync( - schema: Arc>, + schema: Arc>, context: Arc, req: Request, ) -> Response @@ -43,7 +43,7 @@ where /// Executes the provided GraphQL [`Request`] against the provided `schema` in the provided /// `context`, returning the encoded [`Response`]. pub async fn graphql( - schema: Arc>, + schema: Arc>, context: Arc, req: Request, ) -> Response @@ -182,7 +182,7 @@ where } async fn execute_request_sync( - schema: Arc>, + schema: Arc>, context: Arc, request: GraphQLBatchRequest, ) -> Response @@ -213,7 +213,7 @@ where } async fn execute_request( - schema: Arc>, + schema: Arc>, context: Arc, request: GraphQLBatchRequest, ) -> Response diff --git a/juniper_rocket/examples/simple.rs b/juniper_rocket/examples/simple.rs index 30480449f..1959196c7 100644 --- a/juniper_rocket/examples/simple.rs +++ b/juniper_rocket/examples/simple.rs @@ -8,7 +8,7 @@ use juniper::{ }; use rocket::{State, response::content::RawHtml, routes}; -type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = RootNode, EmptySubscription>; #[rocket::get("/")] async fn homepage() -> RawHtml<&'static str> { diff --git a/juniper_rocket/src/lib.rs b/juniper_rocket/src/lib.rs index 25027d7c3..90e01cbdb 100644 --- a/juniper_rocket/src/lib.rs +++ b/juniper_rocket/src/lib.rs @@ -44,7 +44,7 @@ use juniper::{ /// }; /// use rocket::{routes, State}; /// -/// type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +/// type Schema = RootNode, EmptySubscription>; /// /// // GET request accepts query parameters like these: /// // ?query= @@ -179,7 +179,7 @@ where /// Asynchronously execute an incoming GraphQL query. pub async fn execute( &self, - root_node: &RootNode<'_, QueryT, MutationT, SubscriptionT, S>, + root_node: &RootNode, context: &CtxT, ) -> GraphQLResponse where @@ -225,7 +225,7 @@ impl GraphQLResponse { /// # use juniper::tests::fixtures::starwars::schema::{Database, Query}; /// # use juniper::{EmptyMutation, EmptySubscription, FieldError, RootNode, Value}; /// # - /// # type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; + /// # type Schema = RootNode, EmptySubscription>; /// # /// #[rocket::get("/graphql?")] /// fn get_graphql_handler( diff --git a/juniper_rocket/tests/http_test_suite.rs b/juniper_rocket/tests/http_test_suite.rs index 04ae992db..8adeeeb74 100644 --- a/juniper_rocket/tests/http_test_suite.rs +++ b/juniper_rocket/tests/http_test_suite.rs @@ -16,7 +16,7 @@ use rocket::{ post, routes, }; -type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = RootNode, EmptySubscription>; fn bootstrap_rocket() -> Rocket { Rocket::build().manage(Database::new()).manage(Schema::new( diff --git a/juniper_subscriptions/CHANGELOG.md b/juniper_subscriptions/CHANGELOG.md index b77f40a5e..b498cdfbd 100644 --- a/juniper_subscriptions/CHANGELOG.md +++ b/juniper_subscriptions/CHANGELOG.md @@ -10,8 +10,11 @@ All user visible changes to `juniper_subscriptions` crate will be documented in ### BC Breaks +- Removed lifetime parameters from `Coordinator`. ([#1247], [#819]) - Bumped up [MSRV] to 1.85. ([#1272], [todo]) +[#819]: /../../issues/819 +[#1247]: /../../pull/1247 [#1272]: /../../pull/1272 [todo]: /../../commit/todo diff --git a/juniper_subscriptions/examples/basic.rs b/juniper_subscriptions/examples/basic.rs index f433f81e9..8b4eefb81 100644 --- a/juniper_subscriptions/examples/basic.rs +++ b/juniper_subscriptions/examples/basic.rs @@ -40,7 +40,7 @@ impl Subscription { } } -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode, Subscription>; fn schema() -> Schema { Schema::new(Query, EmptyMutation::new(), Subscription) diff --git a/juniper_subscriptions/src/lib.rs b/juniper_subscriptions/src/lib.rs index 949f3f7a2..327d101c6 100644 --- a/juniper_subscriptions/src/lib.rs +++ b/juniper_subscriptions/src/lib.rs @@ -17,7 +17,7 @@ use juniper::{ /// Simple [`SubscriptionCoordinator`] implementation: /// - contains the schema /// - handles subscription start -pub struct Coordinator<'a, QueryT, MutationT, SubscriptionT, CtxT, S> +pub struct Coordinator where QueryT: GraphQLTypeAsync + Send, QueryT::TypeInfo: Send + Sync, @@ -28,11 +28,11 @@ where CtxT: Sync, S: ScalarValue + Send + Sync, { - root_node: juniper::RootNode<'a, QueryT, MutationT, SubscriptionT, S>, + root_node: juniper::RootNode, } -impl<'a, QueryT, MutationT, SubscriptionT, CtxT, S> - Coordinator<'a, QueryT, MutationT, SubscriptionT, CtxT, S> +impl + Coordinator where QueryT: GraphQLTypeAsync + Send, QueryT::TypeInfo: Send + Sync, @@ -44,13 +44,13 @@ where S: ScalarValue + Send + Sync, { /// Builds new [`Coordinator`] with specified `root_node` - pub fn new(root_node: juniper::RootNode<'a, QueryT, MutationT, SubscriptionT, S>) -> Self { + pub fn new(root_node: juniper::RootNode) -> Self { Self { root_node } } } impl<'a, QueryT, MutationT, SubscriptionT, CtxT, S> SubscriptionCoordinator<'a, CtxT, S> - for Coordinator<'a, QueryT, MutationT, SubscriptionT, CtxT, S> + for Coordinator where QueryT: GraphQLTypeAsync + Send, QueryT::TypeInfo: Send + Sync, diff --git a/juniper_warp/examples/subscription.rs b/juniper_warp/examples/subscription.rs index 0dfa9b5d8..00d98a6c1 100644 --- a/juniper_warp/examples/subscription.rs +++ b/juniper_warp/examples/subscription.rs @@ -132,7 +132,7 @@ impl Subscription { } } -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode, Subscription>; fn schema() -> Schema { Schema::new(Query, EmptyMutation::new(), Subscription) diff --git a/juniper_warp/src/lib.rs b/juniper_warp/src/lib.rs index 4c1027a8a..9cd9d989c 100644 --- a/juniper_warp/src/lib.rs +++ b/juniper_warp/src/lib.rs @@ -155,7 +155,7 @@ use self::response::JuniperResponse; /// /// [1]: https://github.com/seanmonstar/warp/issues/388#issuecomment-576453485 pub fn make_graphql_filter( - schema: impl Into>>, + schema: impl Into>>, context_extractor: impl Filter + Send + Sync + 'static, ) -> impl Filter + Clone + Send where @@ -198,7 +198,7 @@ where /// /// [1]: GraphQLBatchRequest::execute_sync pub fn make_graphql_filter_sync( - schema: impl Into>>, + schema: impl Into>>, context_extractor: impl Filter + Send + Sync + 'static, ) -> impl Filter + Clone + Send where @@ -238,7 +238,7 @@ where /// `context`. async fn graphql_handler( req: GraphQLBatchRequest, - schema: Arc>, + schema: Arc>, context: CtxT, ) -> reply::Response where @@ -260,7 +260,7 @@ where /// [1]: GraphQLBatchRequest::execute_sync async fn graphql_handler_sync( req: GraphQLBatchRequest, - schema: Arc>, + schema: Arc>, context: CtxT, ) -> reply::Response where @@ -477,12 +477,8 @@ mod tests { #[tokio::test] async fn post_json() { - type Schema = juniper::RootNode< - 'static, - Query, - EmptyMutation, - EmptySubscription, - >; + type Schema = + juniper::RootNode, EmptySubscription>; let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()); @@ -527,12 +523,8 @@ mod tests { } } - type Schema = juniper::RootNode< - 'static, - Query, - EmptyMutation, - EmptySubscription, - >; + type Schema = + juniper::RootNode, EmptySubscription>; let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()); @@ -575,12 +567,8 @@ mod tests { #[tokio::test] async fn batch_requests() { - type Schema = juniper::RootNode< - 'static, - Query, - EmptyMutation, - EmptySubscription, - >; + type Schema = + juniper::RootNode, EmptySubscription>; let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()); diff --git a/juniper_warp/src/subscriptions.rs b/juniper_warp/src/subscriptions.rs index 53bd54bf3..83fed4fcb 100644 --- a/juniper_warp/src/subscriptions.rs +++ b/juniper_warp/src/subscriptions.rs @@ -177,7 +177,7 @@ impl From for Error { /// [new]: https://github.com/enisdenjo/graphql-ws/blob/v5.14.0/PROTOCOL.md /// [old]: https://github.com/apollographql/subscriptions-transport-ws/blob/v0.11.0/PROTOCOL.md pub fn make_ws_filter( - schema: impl Into>>, + schema: impl Into>>, init: I, ) -> BoxedFilter<(impl Reply,)> where @@ -239,7 +239,7 @@ where /// [old]: https://github.com/apollographql/subscriptions-transport-ws/blob/v0.11.0/PROTOCOL.md pub async fn serve_graphql_ws( websocket: warp::ws::WebSocket, - root_node: Arc>, + root_node: Arc>, init: I, ) -> Result<(), Error> where @@ -286,7 +286,7 @@ where /// [new]: https://github.com/enisdenjo/graphql-ws/blob/v5.14.0/PROTOCOL.md pub async fn serve_graphql_transport_ws( websocket: warp::ws::WebSocket, - root_node: Arc>, + root_node: Arc>, init: I, ) -> Result<(), Error> where diff --git a/tests/codegen/fail/input-object/derive_incompatible_field_type.stderr b/tests/codegen/fail/input-object/derive_incompatible_field_type.stderr index 0edd0d091..1a6c2f371 100644 --- a/tests/codegen/fail/input-object/derive_incompatible_field_type.stderr +++ b/tests/codegen/fail/input-object/derive_incompatible_field_type.stderr @@ -7,12 +7,12 @@ error[E0277]: the trait bound `ObjectA: IsInputType<__S>` is not satisfied = help: the following other types implement trait `IsInputType`: `&T` implements `IsInputType` `Arc` implements `IsInputType` + `ArcStr` implements `IsInputType<__S>` `Box` implements `IsInputType` `ID` implements `IsInputType<__S>` `Object` implements `IsInputType<__S>` `TypeKind` implements `IsInputType<__S>` `Vec` implements `IsInputType` - `[T; N]` implements `IsInputType` and $N others error[E0277]: the trait bound `ObjectA: FromInputValue<__S>` is not satisfied @@ -26,22 +26,22 @@ error[E0277]: the trait bound `ObjectA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `Object` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` - `bool` implements `FromInputValue<__S>` and $N others -note: required by a bound in `Registry::<'r, S>::arg` +note: required by a bound in `Registry::::arg` --> $WORKSPACE/juniper/src/executor/mod.rs | - | pub fn arg(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S> + | pub fn arg(&mut self, name: impl Into, info: &T::TypeInfo) -> Argument | --- required by a bound in this associated function | where | T: GraphQLType + FromInputValue, - | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg` + | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::::arg` error[E0277]: the trait bound `ObjectA: FromInputValue<__S>` is not satisfied --> fail/input-object/derive_incompatible_field_type.rs:8:10 @@ -51,13 +51,13 @@ error[E0277]: the trait bound `ObjectA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `Object` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` - `bool` implements `FromInputValue<__S>` and $N others = note: this error originates in the derive macro `GraphQLInputObject` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -72,9 +72,9 @@ error[E0277]: the trait bound `ObjectA: ToInputValue<_>` is not satisfied `&[T]` implements `ToInputValue` `&str` implements `ToInputValue` `Arc` implements `ToInputValue` + `ArcStr` implements `ToInputValue<__S>` `Box` implements `ToInputValue` `ID` implements `ToInputValue<__S>` `Object` implements `ToInputValue<__S>` - `TypeKind` implements `ToInputValue<__S>` and $N others = note: this error originates in the derive macro `GraphQLInputObject` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/codegen/fail/interface/struct/attr_field_non_output_return_type.stderr b/tests/codegen/fail/interface/struct/attr_field_non_output_return_type.stderr index 83d0b2aff..ed93028b3 100644 --- a/tests/codegen/fail/interface/struct/attr_field_non_output_return_type.stderr +++ b/tests/codegen/fail/interface/struct/attr_field_non_output_return_type.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied = help: the following other types implement trait `IsOutputType`: `&T` implements `IsOutputType` `Arc` implements `IsOutputType` - `Argument<'a, S>` implements `IsOutputType` + `ArcStr` implements `IsOutputType<__S>` + `Argument` implements `IsOutputType` `Box` implements `IsOutputType` `CharacterValueEnum` implements `IsOutputType<__S>` `EnumValue` implements `IsOutputType<__S>` `ID` implements `IsOutputType<__S>` - `SchemaType<'a, S>` implements `IsOutputType` and $N others diff --git a/tests/codegen/fail/interface/struct/derive_field_non_output_return_type.stderr b/tests/codegen/fail/interface/struct/derive_field_non_output_return_type.stderr index 05c193e15..86a147ab6 100644 --- a/tests/codegen/fail/interface/struct/derive_field_non_output_return_type.stderr +++ b/tests/codegen/fail/interface/struct/derive_field_non_output_return_type.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied = help: the following other types implement trait `IsOutputType`: `&T` implements `IsOutputType` `Arc` implements `IsOutputType` - `Argument<'a, S>` implements `IsOutputType` + `ArcStr` implements `IsOutputType<__S>` + `Argument` implements `IsOutputType` `Box` implements `IsOutputType` `CharacterValueEnum` implements `IsOutputType<__S>` `EnumValue` implements `IsOutputType<__S>` `ID` implements `IsOutputType<__S>` - `SchemaType<'a, S>` implements `IsOutputType` and $N others diff --git a/tests/codegen/fail/interface/trait/argument_non_input_type.stderr b/tests/codegen/fail/interface/trait/argument_non_input_type.stderr index e59ba502a..cc6a10038 100644 --- a/tests/codegen/fail/interface/trait/argument_non_input_type.stderr +++ b/tests/codegen/fail/interface/trait/argument_non_input_type.stderr @@ -7,12 +7,12 @@ error[E0277]: the trait bound `ObjA: IsInputType<__S>` is not satisfied = help: the following other types implement trait `IsInputType`: `&T` implements `IsInputType` `Arc` implements `IsInputType` + `ArcStr` implements `IsInputType<__S>` `Box` implements `IsInputType` `ID` implements `IsInputType<__S>` `TypeKind` implements `IsInputType<__S>` `Vec` implements `IsInputType` `[T; N]` implements `IsInputType` - `[T]` implements `IsInputType` and $N others error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied @@ -26,19 +26,19 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` `bool` implements `FromInputValue<__S>` - `f64` implements `FromInputValue<__S>` and $N others -note: required by a bound in `Registry::<'r, S>::arg` +note: required by a bound in `Registry::::arg` --> $WORKSPACE/juniper/src/executor/mod.rs | - | pub fn arg(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S> + | pub fn arg(&mut self, name: impl Into, info: &T::TypeInfo) -> Argument | --- required by a bound in this associated function | where | T: GraphQLType + FromInputValue, - | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg` + | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::::arg` diff --git a/tests/codegen/fail/interface/trait/field_non_output_return_type.stderr b/tests/codegen/fail/interface/trait/field_non_output_return_type.stderr index 503dc603f..0561770b2 100644 --- a/tests/codegen/fail/interface/trait/field_non_output_return_type.stderr +++ b/tests/codegen/fail/interface/trait/field_non_output_return_type.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied = help: the following other types implement trait `IsOutputType`: `&T` implements `IsOutputType` `Arc` implements `IsOutputType` - `Argument<'a, S>` implements `IsOutputType` + `ArcStr` implements `IsOutputType<__S>` + `Argument` implements `IsOutputType` `Box` implements `IsOutputType` `CharacterValueEnum` implements `IsOutputType<__S>` `EnumValue` implements `IsOutputType<__S>` `ID` implements `IsOutputType<__S>` - `SchemaType<'a, S>` implements `IsOutputType` and $N others diff --git a/tests/codegen/fail/object/argument_non_input_type.stderr b/tests/codegen/fail/object/argument_non_input_type.stderr index de47b5498..b0ea88e24 100644 --- a/tests/codegen/fail/object/argument_non_input_type.stderr +++ b/tests/codegen/fail/object/argument_non_input_type.stderr @@ -7,12 +7,12 @@ error[E0277]: the trait bound `ObjA: IsInputType<__S>` is not satisfied = help: the following other types implement trait `IsInputType`: `&T` implements `IsInputType` `Arc` implements `IsInputType` + `ArcStr` implements `IsInputType<__S>` `Box` implements `IsInputType` `ID` implements `IsInputType<__S>` `TypeKind` implements `IsInputType<__S>` `Vec` implements `IsInputType` `[T; N]` implements `IsInputType` - `[T]` implements `IsInputType` and $N others error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied @@ -26,22 +26,22 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` `bool` implements `FromInputValue<__S>` - `f64` implements `FromInputValue<__S>` and $N others -note: required by a bound in `Registry::<'r, S>::arg` +note: required by a bound in `Registry::::arg` --> $WORKSPACE/juniper/src/executor/mod.rs | - | pub fn arg(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S> + | pub fn arg(&mut self, name: impl Into, info: &T::TypeInfo) -> Argument | --- required by a bound in this associated function | where | T: GraphQLType + FromInputValue, - | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg` + | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::::arg` error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied --> fail/object/argument_non_input_type.rs:10:1 @@ -51,13 +51,13 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` `bool` implements `FromInputValue<__S>` - `f64` implements `FromInputValue<__S>` and $N others = note: this error originates in the attribute macro `graphql_object` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -69,13 +69,13 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` `bool` implements `FromInputValue<__S>` - `f64` implements `FromInputValue<__S>` and $N others warning: unused variable: `obj` diff --git a/tests/codegen/fail/object/attr_field_non_output_return_type.stderr b/tests/codegen/fail/object/attr_field_non_output_return_type.stderr index 11dffc15f..2cf539d98 100644 --- a/tests/codegen/fail/object/attr_field_non_output_return_type.stderr +++ b/tests/codegen/fail/object/attr_field_non_output_return_type.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied = help: the following other types implement trait `IsOutputType`: `&T` implements `IsOutputType` `Arc` implements `IsOutputType` - `Argument<'a, S>` implements `IsOutputType` + `ArcStr` implements `IsOutputType<__S>` + `Argument` implements `IsOutputType` `Box` implements `IsOutputType` `EnumValue` implements `IsOutputType<__S>` `ID` implements `IsOutputType<__S>` `ObjA` implements `IsOutputType<__S>` - `SchemaType<'a, S>` implements `IsOutputType` and $N others diff --git a/tests/codegen/fail/object/derive_field_non_output_return_type.stderr b/tests/codegen/fail/object/derive_field_non_output_return_type.stderr index f06516149..a3b691e27 100644 --- a/tests/codegen/fail/object/derive_field_non_output_return_type.stderr +++ b/tests/codegen/fail/object/derive_field_non_output_return_type.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied = help: the following other types implement trait `IsOutputType`: `&T` implements `IsOutputType` `Arc` implements `IsOutputType` - `Argument<'a, S>` implements `IsOutputType` + `ArcStr` implements `IsOutputType<__S>` + `Argument` implements `IsOutputType` `Box` implements `IsOutputType` `EnumValue` implements `IsOutputType<__S>` `ID` implements `IsOutputType<__S>` `ObjA` implements `IsOutputType<__S>` - `SchemaType<'a, S>` implements `IsOutputType` and $N others diff --git a/tests/codegen/fail/subscription/argument_non_input_type.stderr b/tests/codegen/fail/subscription/argument_non_input_type.stderr index 69463a952..49ce64303 100644 --- a/tests/codegen/fail/subscription/argument_non_input_type.stderr +++ b/tests/codegen/fail/subscription/argument_non_input_type.stderr @@ -15,12 +15,12 @@ error[E0277]: the trait bound `ObjA: IsInputType<__S>` is not satisfied = help: the following other types implement trait `IsInputType`: `&T` implements `IsInputType` `Arc` implements `IsInputType` + `ArcStr` implements `IsInputType<__S>` `Box` implements `IsInputType` `ID` implements `IsInputType<__S>` `TypeKind` implements `IsInputType<__S>` `Vec` implements `IsInputType` `[T; N]` implements `IsInputType` - `[T]` implements `IsInputType` and $N others error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied @@ -34,22 +34,22 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` `bool` implements `FromInputValue<__S>` - `f64` implements `FromInputValue<__S>` and $N others -note: required by a bound in `Registry::<'r, S>::arg` +note: required by a bound in `Registry::::arg` --> $WORKSPACE/juniper/src/executor/mod.rs | - | pub fn arg(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S> + | pub fn arg(&mut self, name: impl Into, info: &T::TypeInfo) -> Argument | --- required by a bound in this associated function | where | T: GraphQLType + FromInputValue, - | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg` + | ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::::arg` error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied --> fail/subscription/argument_non_input_type.rs:15:1 @@ -59,13 +59,13 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` `bool` implements `FromInputValue<__S>` - `f64` implements `FromInputValue<__S>` and $N others = note: this error originates in the attribute macro `graphql_subscription` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -77,11 +77,11 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied | = help: the following other types implement trait `FromInputValue`: `Arc` implements `FromInputValue` + `ArcStr` implements `FromInputValue<__S>` `Box` implements `FromInputValue` `ID` implements `FromInputValue<__S>` `TypeKind` implements `FromInputValue<__S>` `Vec` implements `FromInputValue` `[T; N]` implements `FromInputValue` `bool` implements `FromInputValue<__S>` - `f64` implements `FromInputValue<__S>` and $N others diff --git a/tests/codegen/fail/subscription/field_non_output_return_type.stderr b/tests/codegen/fail/subscription/field_non_output_return_type.stderr index fbc3506ff..4d5fecd4a 100644 --- a/tests/codegen/fail/subscription/field_non_output_return_type.stderr +++ b/tests/codegen/fail/subscription/field_non_output_return_type.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied = help: the following other types implement trait `IsOutputType`: `&T` implements `IsOutputType` `Arc` implements `IsOutputType` - `Argument<'a, S>` implements `IsOutputType` + `ArcStr` implements `IsOutputType<__S>` + `Argument` implements `IsOutputType` `Box` implements `IsOutputType` `EnumValue` implements `IsOutputType<__S>` `ID` implements `IsOutputType<__S>` `ObjA` implements `IsOutputType<__S>` - `SchemaType<'a, S>` implements `IsOutputType` and $N others diff --git a/tests/codegen/fail/union/enum_non_object_variant.stderr b/tests/codegen/fail/union/enum_non_object_variant.stderr index cd515b2d9..bf1092424 100644 --- a/tests/codegen/fail/union/enum_non_object_variant.stderr +++ b/tests/codegen/fail/union/enum_non_object_variant.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` diff --git a/tests/codegen/fail/union/enum_same_type_ugly.stderr b/tests/codegen/fail/union/enum_same_type_ugly.stderr index bf365e189..b68e7ec41 100644 --- a/tests/codegen/fail/union/enum_same_type_ugly.stderr +++ b/tests/codegen/fail/union/enum_same_type_ugly.stderr @@ -18,12 +18,12 @@ error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not s = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not satisfied @@ -35,10 +35,10 @@ error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not s = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` diff --git a/tests/codegen/fail/union/struct_non_object_variant.stderr b/tests/codegen/fail/union/struct_non_object_variant.stderr index 00dbbccac..16849490c 100644 --- a/tests/codegen/fail/union/struct_non_object_variant.stderr +++ b/tests/codegen/fail/union/struct_non_object_variant.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` diff --git a/tests/codegen/fail/union/struct_same_type_ugly.stderr b/tests/codegen/fail/union/struct_same_type_ugly.stderr index 23ef801cf..e926cc421 100644 --- a/tests/codegen/fail/union/struct_same_type_ugly.stderr +++ b/tests/codegen/fail/union/struct_same_type_ugly.stderr @@ -18,12 +18,12 @@ error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not s = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not satisfied @@ -35,10 +35,10 @@ error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not s = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` diff --git a/tests/codegen/fail/union/trait_non_object_variant.stderr b/tests/codegen/fail/union/trait_non_object_variant.stderr index 8008fa28e..e86d69a73 100644 --- a/tests/codegen/fail/union/trait_non_object_variant.stderr +++ b/tests/codegen/fail/union/trait_non_object_variant.stderr @@ -7,10 +7,10 @@ error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` diff --git a/tests/codegen/fail/union/trait_same_type_ugly.stderr b/tests/codegen/fail/union/trait_same_type_ugly.stderr index e017c6ffd..63d5b2b54 100644 --- a/tests/codegen/fail/union/trait_same_type_ugly.stderr +++ b/tests/codegen/fail/union/trait_same_type_ugly.stderr @@ -18,12 +18,12 @@ error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not s = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not satisfied @@ -35,10 +35,10 @@ error[E0277]: the trait bound `std::string::String: GraphQLObject<__S>` is not s = help: the following other types implement trait `GraphQLObject`: `&T` implements `GraphQLObject` `Arc` implements `GraphQLObject` - `Argument<'a, S>` implements `GraphQLObject` + `Argument` implements `GraphQLObject` `Box` implements `GraphQLObject` `EnumValue` implements `GraphQLObject<__S>` - `SchemaType<'a, S>` implements `GraphQLObject` - `juniper::meta::Field<'a, S>` implements `GraphQLObject` - `juniper::schema::model::DirectiveType<'a, S>` implements `GraphQLObject` + `SchemaType` implements `GraphQLObject` + `juniper::meta::Field` implements `GraphQLObject` + `juniper::schema::model::DirectiveType` implements `GraphQLObject` `juniper::schema::model::TypeType<'a, S>` implements `GraphQLObject` diff --git a/tests/integration/tests/codegen_subscription_attr.rs b/tests/integration/tests/codegen_subscription_attr.rs index 78985d843..986d6afd2 100644 --- a/tests/integration/tests/codegen_subscription_attr.rs +++ b/tests/integration/tests/codegen_subscription_attr.rs @@ -29,25 +29,25 @@ impl Query { } } -fn schema<'q, C, Qry, Sub>( +fn schema( query_root: Qry, subscription_root: Sub, -) -> RootNode<'q, Qry, EmptyMutation, Sub> +) -> RootNode, Sub> where - Qry: GraphQLType + 'q, - Sub: GraphQLType + 'q, + Qry: GraphQLType, + Sub: GraphQLType, { RootNode::new(query_root, EmptyMutation::::new(), subscription_root) } -fn schema_with_scalar<'q, S, C, Qry, Sub>( +fn schema_with_scalar( query_root: Qry, subscription_root: Sub, -) -> RootNode<'q, Qry, EmptyMutation, Sub, S> +) -> RootNode, Sub, S> where - Qry: GraphQLType + 'q, - Sub: GraphQLType + 'q, - S: ScalarValue + 'q, + Qry: GraphQLType, + Sub: GraphQLType, + S: ScalarValue, { RootNode::new_with_scalar_value(query_root, EmptyMutation::::new(), subscription_root) } diff --git a/tests/integration/tests/common/mod.rs b/tests/integration/tests/common/mod.rs index 57f4849df..16dae58e0 100644 --- a/tests/integration/tests/common/mod.rs +++ b/tests/integration/tests/common/mod.rs @@ -11,11 +11,9 @@ pub mod util { GraphQLType, RootNode, ScalarValue, Value, ValuesStream, graphql_value, }; - pub fn schema<'q, C, Q>( - query_root: Q, - ) -> RootNode<'q, Q, EmptyMutation, EmptySubscription> + pub fn schema(query_root: Q) -> RootNode, EmptySubscription> where - Q: GraphQLType + 'q, + Q: GraphQLType, { RootNode::new( query_root, @@ -24,12 +22,12 @@ pub mod util { ) } - pub fn schema_with_scalar<'q, S, C, Q>( + pub fn schema_with_scalar( query_root: Q, - ) -> RootNode<'q, Q, EmptyMutation, EmptySubscription, S> + ) -> RootNode, EmptySubscription, S> where - Q: GraphQLType + 'q, - S: ScalarValue + 'q, + Q: GraphQLType, + S: ScalarValue, { RootNode::new_with_scalar_value( query_root, diff --git a/tests/integration/tests/cve_2022_31173.rs b/tests/integration/tests/cve_2022_31173.rs index 7ffee6a34..4764641e1 100644 --- a/tests/integration/tests/cve_2022_31173.rs +++ b/tests/integration/tests/cve_2022_31173.rs @@ -29,7 +29,7 @@ impl Query { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode; #[tokio::test] async fn test() { diff --git a/tests/integration/tests/explicit_null.rs b/tests/integration/tests/explicit_null.rs index b54c9a9db..59a05dc89 100644 --- a/tests/integration/tests/explicit_null.rs +++ b/tests/integration/tests/explicit_null.rs @@ -25,7 +25,7 @@ impl Query { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode, EmptySubscription>; #[tokio::test] async fn explicit_null() { diff --git a/tests/integration/tests/issue_1287.rs b/tests/integration/tests/issue_1287.rs index c5e0d3e91..25d1eb332 100644 --- a/tests/integration/tests/issue_1287.rs +++ b/tests/integration/tests/issue_1287.rs @@ -25,7 +25,7 @@ impl Query { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode; #[tokio::test] async fn error_propagates_same_way() { diff --git a/tests/integration/tests/issue_371.rs b/tests/integration/tests/issue_371.rs index d0df9b640..81cf0cd29 100644 --- a/tests/integration/tests/issue_371.rs +++ b/tests/integration/tests/issue_371.rs @@ -57,7 +57,7 @@ impl Country { } } -type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = RootNode, EmptySubscription>; #[tokio::test] async fn users() { diff --git a/tests/integration/tests/issue_398.rs b/tests/integration/tests/issue_398.rs index 1a402abe4..05062550c 100644 --- a/tests/integration/tests/issue_398.rs +++ b/tests/integration/tests/issue_398.rs @@ -50,7 +50,7 @@ impl Country { } } -type Schema = RootNode<'static, Query, EmptyMutation<()>, EmptySubscription<()>>; +type Schema = RootNode, EmptySubscription<()>>; #[tokio::test] async fn lookahead_from_fragment_with_nested_type() { diff --git a/tests/integration/tests/issue_407.rs b/tests/integration/tests/issue_407.rs index 62d69f61f..a3d73c0bc 100644 --- a/tests/integration/tests/issue_407.rs +++ b/tests/integration/tests/issue_407.rs @@ -43,7 +43,7 @@ impl Query { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode; #[tokio::test] async fn fragments_in_interface() { diff --git a/tests/integration/tests/issue_500.rs b/tests/integration/tests/issue_500.rs index 332120b1a..69b522de2 100644 --- a/tests/integration/tests/issue_500.rs +++ b/tests/integration/tests/issue_500.rs @@ -63,7 +63,7 @@ impl Country { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation<()>, EmptySubscription<()>>; +type Schema = juniper::RootNode, EmptySubscription<()>>; #[tokio::test] async fn nested_fragments() { diff --git a/tests/integration/tests/issue_798.rs b/tests/integration/tests/issue_798.rs index afb100dd5..9bdbd6e1e 100644 --- a/tests/integration/tests/issue_798.rs +++ b/tests/integration/tests/issue_798.rs @@ -54,7 +54,7 @@ impl Query { } } -type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = RootNode; #[tokio::test] async fn interface_inline_fragment_on_union() { diff --git a/tests/integration/tests/issue_914.rs b/tests/integration/tests/issue_914.rs index 58ea080b5..c0864e28b 100644 --- a/tests/integration/tests/issue_914.rs +++ b/tests/integration/tests/issue_914.rs @@ -33,7 +33,7 @@ impl Query { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode; #[tokio::test] async fn fragments_with_nested_objects_dont_override_previous_selections() { diff --git a/tests/integration/tests/issue_922.rs b/tests/integration/tests/issue_922.rs index a4aa62260..585d2eb9b 100644 --- a/tests/integration/tests/issue_922.rs +++ b/tests/integration/tests/issue_922.rs @@ -46,7 +46,7 @@ struct Droid { pub name: String, } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode; #[tokio::test] async fn object_fragment_on_interface() { diff --git a/tests/integration/tests/issue_925.rs b/tests/integration/tests/issue_925.rs index e3a8a796d..79dee3127 100644 --- a/tests/integration/tests/issue_925.rs +++ b/tests/integration/tests/issue_925.rs @@ -46,7 +46,7 @@ impl Query { } } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, SubscriptionsRoot>; +type Schema = juniper::RootNode; #[tokio::test] async fn error_extensions() { diff --git a/tests/integration/tests/issue_945.rs b/tests/integration/tests/issue_945.rs index f266b4453..20cb65b63 100644 --- a/tests/integration/tests/issue_945.rs +++ b/tests/integration/tests/issue_945.rs @@ -40,7 +40,7 @@ struct Droid { pub sensor_color: String, } -type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>; +type Schema = juniper::RootNode; #[tokio::test] async fn fragment_on_union() { diff --git a/tests/integration/tests/pre_parse.rs b/tests/integration/tests/pre_parse.rs index ff31baf77..561133169 100644 --- a/tests/integration/tests/pre_parse.rs +++ b/tests/integration/tests/pre_parse.rs @@ -43,7 +43,7 @@ impl User { } } -type Schema = RootNode<'static, Query, EmptyMutation, Subscription>; +type Schema = RootNode, Subscription>; #[tokio::test] async fn query_document_can_be_pre_parsed() {