diff --git a/benches/src/lib.rs b/benches/src/lib.rs
index c8ad5b512..24d481034 100644
--- a/benches/src/lib.rs
+++ b/benches/src/lib.rs
@@ -89,8 +89,7 @@ impl Query {
     }
 }
 
-pub fn new_schema() -> RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>
-{
+pub fn new_schema() -> RootNode<Query, EmptyMutation<Context>, EmptySubscription<Context>> {
     RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new())
 }
 
diff --git a/book/src/quickstart.md b/book/src/quickstart.md
index bc830d448..3fdc2a0e3 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<Context>>;
+type Schema = juniper::RootNode<Query, Mutation, EmptySubscription<Context>>;
 #
 # fn main() {
 #     _ = Schema::new(Query, Mutation, EmptySubscription::new());
@@ -190,7 +190,7 @@ impl Query {
     }
 }
 
-type Schema = juniper::RootNode<'static, Query, EmptyMutation<Ctx>, EmptySubscription<Ctx>>;
+type Schema = juniper::RootNode<Query, EmptyMutation<Ctx>, EmptySubscription<Ctx>>;
 
 fn main() {
     // Create a context.
diff --git a/book/src/schema/index.md b/book/src/schema/index.md
index 20723f16a..d0c14bce6 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<Query, Mutation, EmptySubscription>;
 #
 # fn main() {}
 ```
@@ -138,7 +138,7 @@ impl Query {
    }
 }
 
-type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>;
+type Schema = RootNode<Query, EmptyMutation, EmptySubscription>;
 
 fn main() {
     // Run the built-in introspection query.
diff --git a/book/src/schema/introspection.md b/book/src/schema/introspection.md
index 469282d66..25a8d841a 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<Query, EmptyMutation, EmptySubscription>;
 
 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 0de59d3da..1686190f5 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<Database>, Subscription>;
+type Schema = RootNode<Query, EmptyMutation<Database>, Subscription>;
 
 fn schema() -> Schema {
     Schema::new(Query, EmptyMutation::new(), Subscription)
diff --git a/juniper/CHANGELOG.md b/juniper/CHANGELOG.md
index 6d57170b8..e06848975 100644
--- a/juniper/CHANGELOG.md
+++ b/juniper/CHANGELOG.md
@@ -6,19 +6,29 @@ All user visible changes to `juniper` crate will be documented in this file. Thi
 
 
 
-## [0.17.0] · 2024-04-?? (unreleased)
-[0.17.0]: /../../tree/juniper-v0.17.0/juniper
+## master
 
-[Diff](/../../compare/juniper-v0.16.1...juniper-v0.17.0) | [Milestone](/../../milestone/7)
+[Diff](/../../compare/juniper-v0.16.1...master) | [Milestone](/../../milestone/7)
 
 ### BC Breaks
 
 - Upgraded [`chrono-tz` crate] integration to [0.9 version](https://github.com/chronotope/chrono-tz/releases/tag/v0.9.0). ([#1252])
+- Optimized schema implementation with [`arcstr` crate]: ([#1247], [#819])
+    - Removed lifetime parameters from `MetaType` and its members.
+    - Made `MetaType::name()`, `MetaType::description()` and `MetaType::specified_by_url()` returning `ArcStr`.
+    - Made `DeprecationStatus::reason()` returning `ArcStr`.
+    - Removed lifetime parameters from `DirectiveType`.
+    - Made `DirectiveType::name` and `DirectiveType::description` using `ArcStr`.
+    - Made `types::Name` and `types::NameParseError` using `ArcStr` instead of `String`.
+    - Made `GraphQLType::name()` and `GraphQLValue::type_name()` returning `ArcStr`.
+    - Removed lifetime parameters from `RootNode`.
 
 ### Changed
 
 - Updated [GraphiQL] to [3.2.0 version](https://github.com/graphql/graphiql/blob/graphiql%403.2.0/packages/graphiql/CHANGELOG.md#320). ([#1253])
 
+[#819]: /../../issues/819
+[#1247]: /../../pull/1247
 [#1252]: /../../pull/1252
 [#1253]: /../../pull/1253
 
@@ -217,6 +227,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 9ff926d43..c9600dc1a 100644
--- a/juniper/Cargo.toml
+++ b/juniper/Cargo.toml
@@ -42,6 +42,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 }
@@ -57,7 +58,6 @@ rust_decimal = { version = "1.20", default-features = false, optional = true }
 ryu = { version = "1.0", optional = true }
 serde = { version = "1.0.122", features = ["derive"] }
 serde_json = { version = "1.0.18", features = ["std"], default-features = false, optional = true }
-smartstring = "1.0"
 static_assertions = "1.1"
 time = { version = "0.3.35", features = ["formatting", "macros", "parsing"], optional = true }
 url = { version = "2.0", optional = true }
diff --git a/juniper/src/ast.rs b/juniper/src/ast.rs
index 3a3c4de31..87deafaeb 100644
--- a/juniper/src/ast.rs
+++ b/juniper/src/ast.rs
@@ -1,4 +1,12 @@
-use std::{borrow::Cow, fmt, hash::Hash, slice, vec};
+use std::{
+    borrow::{Borrow, Cow},
+    fmt,
+    hash::Hash,
+    ops::Deref,
+    slice, vec,
+};
+
+use arcstr::ArcStr;
 
 use indexmap::IndexMap;
 
@@ -8,34 +16,176 @@ use crate::{
     value::{DefaultScalarValue, ScalarValue},
 };
 
-/// A type literal in the syntax tree
+/// Name of a [`Type`] literal.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum TypeName<'a> {
+    /// Owned version of this name.
+    Owned(ArcStr),
+
+    /// Borrowed version of this name.
+    Borrowed(&'a str),
+}
+
+impl fmt::Display for TypeName<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Owned(n) => fmt::Display::fmt(n, f),
+            Self::Borrowed(n) => fmt::Display::fmt(n, f),
+        }
+    }
+}
+
+impl AsRef<str> for TypeName<'_> {
+    fn as_ref(&self) -> &str {
+        match self {
+            Self::Owned(n) => n.as_ref(),
+            Self::Borrowed(n) => n,
+        }
+    }
+}
+
+impl Borrow<str> for TypeName<'_> {
+    fn borrow(&self) -> &str {
+        self.as_ref()
+    }
+}
+
+impl Deref for TypeName<'_> {
+    type Target = str;
+
+    fn deref(&self) -> &Self::Target {
+        self.as_ref()
+    }
+}
+
+impl<'a> From<&'a str> for TypeName<'a> {
+    fn from(v: &'a str) -> Self {
+        Self::Borrowed(v)
+    }
+}
+
+impl From<ArcStr> for TypeName<'_> {
+    fn from(v: ArcStr) -> Self {
+        Self::Owned(v)
+    }
+}
+
+impl<'a> From<&'a ArcStr> for TypeName<'a> {
+    fn from(v: &'a ArcStr) -> Self {
+        Self::Borrowed(v.as_ref())
+    }
+}
+
+impl From<TypeName<'_>> for Box<str> {
+    fn from(n: TypeName<'_>) -> Self {
+        n.as_ref().into()
+    }
+}
+
+impl From<&TypeName<'_>> for Box<str> {
+    fn from(n: &TypeName<'_>) -> Self {
+        n.as_ref().into()
+    }
+}
+
+impl TypeName<'_> {
+    /// Return owned value if this [`TypeName`].
+    ///
+    /// [`Clone`]s if it's [`ArcStr`] already, otherwise allocates a new one.
+    #[must_use]
+    pub fn to_owned(&self) -> ArcStr {
+        match self {
+            Self::Owned(n) => n.clone(),
+            Self::Borrowed(n) => (*n).into(),
+        }
+    }
+}
+
+/// 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)]
+/// This enum carries no semantic information and might refer to types that do not exist.
+#[derive(Clone, Debug, Eq, PartialEq)]
 pub enum Type<'a> {
-    /// A nullable named type, e.g. `String`
-    Named(Cow<'a, str>),
-    /// A nullable list type, e.g. `[String]`
+    /// `null`able named type, e.g. `String`.
+    Named(TypeName<'a>),
+
+    /// `null`able list type, e.g. `[String]`.
     ///
-    /// The list itself is what's nullable, the containing type might be non-null.
+    /// The list itself is `null`able, the containing [`Type`] might be non-`null`.
     List(Box<Type<'a>>, Option<usize>),
-    /// A non-null named type, e.g. `String!`
-    NonNullNamed(Cow<'a, str>),
-    /// A non-null list type, e.g. `[String]!`.
+
+    /// Non-`null` named type, e.g. `String!`.
+    NonNullNamed(TypeName<'a>),
+
+    /// Non-`null` list type, e.g. `[String]!`.
     ///
-    /// The list itself is what's non-null, the containing type might be null.
+    /// The list itself is non-`null`, the containing [`Type`] might be `null`able.
     NonNullList(Box<Type<'a>>, Option<usize>),
 }
 
+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<'a> Type<'a> {
+    /// 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) -> &TypeName<'_> {
+        match self {
+            Self::Named(n) | Self::NonNullNamed(n) => n,
+            Self::List(l, ..) | Self::NonNullList(l, ..) => l.innermost_name(),
+        }
+    }
+
+    /// Returns the owned innermost name of this [`Type`] by unpacking lists.
+    ///
+    /// All [`Type`] literals contain exactly one named type.
+    #[must_use]
+    pub fn to_innermost_name(&self) -> ArcStr {
+        match self.innermost_name() {
+            TypeName::Owned(n) => n.clone(),
+            TypeName::Borrowed(n) => (*n).into(),
+        }
+    }
+
+    /// 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
 /// out-of-band, or in-band as default variable values. These are _not_ constant
 /// and might contain variables.
 ///
 /// 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)]
 #[allow(missing_docs)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum InputValue<S = DefaultScalarValue> {
     Null,
     Scalar(S),
@@ -45,24 +195,24 @@ pub enum InputValue<S = DefaultScalarValue> {
     Object(Vec<(Spanning<String>, Spanning<InputValue<S>>)>),
 }
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct VariableDefinition<'a, S> {
     pub var_type: Spanning<Type<'a>>,
     pub default_value: Option<Spanning<InputValue<S>>>,
     pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
 }
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct Arguments<'a, S> {
     pub items: Vec<(Spanning<&'a str>, Spanning<InputValue<S>>)>,
 }
 
-#[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<Spanning<&'a str>>,
     pub name: Spanning<&'a str>,
@@ -71,13 +221,13 @@ pub struct Field<'a, S> {
     pub selection_set: Option<Vec<Selection<'a, S>>>,
 }
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct FragmentSpread<'a, S> {
     pub name: Spanning<&'a str>,
     pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
 }
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct InlineFragment<'a, S> {
     pub type_condition: Option<Spanning<&'a str>>,
     pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
@@ -99,7 +249,7 @@ pub struct InlineFragment<'a, S> {
 ///   }
 /// }
 /// ```
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 #[allow(missing_docs)]
 pub enum Selection<'a, S = DefaultScalarValue> {
     Field(Spanning<Field<'a, S>>),
@@ -107,7 +257,7 @@ pub enum Selection<'a, S = DefaultScalarValue> {
     InlineFragment(Spanning<InlineFragment<'a, S>>),
 }
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct Directive<'a, S> {
     pub name: Spanning<&'a str>,
     pub arguments: Option<Spanning<Arguments<'a, S>>>,
@@ -122,7 +272,7 @@ pub enum OperationType {
 }
 
 #[allow(missing_docs)]
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct Operation<'a, S> {
     pub operation_type: OperationType,
     pub name: Option<Spanning<&'a str>>,
@@ -131,7 +281,7 @@ pub struct Operation<'a, S> {
     pub selection_set: Vec<Selection<'a, S>>,
 }
 
-#[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 +290,7 @@ pub struct Fragment<'a, S> {
 }
 
 #[doc(hidden)]
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum Definition<'a, S> {
     Operation(Spanning<Operation<'a, S>>),
     Fragment(Spanning<Fragment<'a, S>>),
@@ -194,44 +344,6 @@ pub trait ToInputValue<S = DefaultScalarValue>: Sized {
     fn to_input_value(&self) -> InputValue<S>;
 }
 
-impl<'a> Type<'a> {
-    /// 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<'a> fmt::Display for Type<'a> {
-    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<S> InputValue<S> {
     /// Construct a `null` value.
     pub fn null() -> Self {
@@ -574,7 +686,7 @@ impl<'a, S> Arguments<'a, S> {
 }
 
 impl<'a, S> VariableDefinitions<'a, S> {
-    pub fn iter(&self) -> slice::Iter<(Spanning<&'a str>, VariableDefinition<S>)> {
+    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 d091bbf8d..112e14e89 100644
--- a/juniper/src/executor/mod.rs
+++ b/juniper/src/executor/mod.rs
@@ -8,13 +8,14 @@ use std::{
     sync::{Arc, RwLock},
 };
 
+use arcstr::ArcStr;
 use fnv::FnvHashMap;
 use futures::Stream;
 
 use crate::{
     ast::{
         Definition, Document, Fragment, FromInputValue, InputValue, Operation, OperationType,
-        Selection, ToInputValue, Type,
+        Selection, ToInputValue, Type, TypeName,
     },
     parser::{SourcePosition, Spanning},
     schema::{
@@ -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<Name, MetaType<'r, S>>,
-}
-
 #[allow(missing_docs)]
 #[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<S>,
     context: &'a CtxT,
     errors: &'r RwLock<Vec<ExecutionError<S>>>,
     field_path: Arc<FieldPath<'a>>,
@@ -898,7 +889,7 @@ where
 pub async fn execute_validated_query_async<'a, 'b, QueryT, MutationT, SubscriptionT, S>(
     document: &'b Document<'a, S>,
     operation: &'b Spanning<Operation<'_, S>>,
-    root_node: &RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
+    root_node: &RootNode<QueryT, MutationT, SubscriptionT, S>,
     variables: &Variables<S>,
     context: &QueryT::Context,
 ) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError>
@@ -1042,7 +1033,7 @@ pub async fn resolve_validated_subscription<
 >(
     document: &Document<'d, S>,
     operation: &Spanning<Operation<'op, S>>,
-    root_node: &'r RootNode<'r, QueryT, MutationT, SubscriptionT, S>,
+    root_node: &'r RootNode<QueryT, MutationT, SubscriptionT, S>,
     variables: &Variables<S>,
     context: &'r QueryT::Context,
 ) -> Result<(Value<ValuesStream<'r, S>>, Vec<ExecutionError<S>>), GraphQLError>
@@ -1138,46 +1129,55 @@ 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<S = DefaultScalarValue> {
+    /// Currently registered types
+    pub types: FnvHashMap<Name, MetaType<S>>,
+}
+
+impl<S> Registry<S> {
     /// Constructs a new [`Registry`] out of the given `types`.
-    pub fn new(types: FnvHashMap<Name, MetaType<'r, S>>) -> Self {
+    pub fn new(types: FnvHashMap<Name, MetaType<S>>) -> 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<T>(&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<T>(&mut self, info: &T::TypeInfo) -> Type<'static>
     where
         T: GraphQLType<S> + ?Sized,
         S: ScalarValue,
     {
         if let Some(name) = T::name(info) {
-            let validated_name = name.parse::<Name>().unwrap();
-            if !self.types.contains_key(name) {
+            let validated_name = Name::new(name.clone()).unwrap();
+            if !self.types.contains_key(&name) {
                 self.insert_placeholder(
                     validated_name.clone(),
-                    Type::NonNullNamed(Cow::Owned(name.into())),
+                    Type::NonNullNamed(TypeName::Owned(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<T>(&mut self, name: &str, info: &T::TypeInfo) -> Field<'r, S>
+    pub fn field<T>(&mut self, name: impl Into<ArcStr>, info: &T::TypeInfo) -> Field<S>
     where
         T: GraphQLType<S> + ?Sized,
         S: ScalarValue,
     {
         Field {
-            name: smartstring::SmartString::from(name),
+            name: name.into(),
             description: None,
             arguments: None,
             field_type: self.get_type::<T>(info),
@@ -1188,9 +1188,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<ArcStr>,
         info: &I::TypeInfo,
-    ) -> Field<'r, S>
+    ) -> Field<S>
     where
         I: GraphQLType<S>,
         S: ScalarValue,
@@ -1205,7 +1205,7 @@ impl<'r, S: 'r> Registry<'r, S> {
     }
 
     /// Creates an [`Argument`] with the provided `name`.
-    pub fn arg<T>(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S>
+    pub fn arg<T>(&mut self, name: impl Into<ArcStr>, info: &T::TypeInfo) -> Argument<S>
     where
         T: GraphQLType<S> + FromInputValue<S>,
         S: ScalarValue,
@@ -1216,10 +1216,10 @@ impl<'r, S: 'r> Registry<'r, S> {
     /// Creates an [`Argument`] with the provided default `value`.
     pub fn arg_with_default<T>(
         &mut self,
-        name: &str,
+        name: impl Into<ArcStr>,
         value: &T,
         info: &T::TypeInfo,
-    ) -> Argument<'r, S>
+    ) -> Argument<S>
     where
         T: GraphQLType<S> + ToInputValue<S> + FromInputValue<S>,
         S: ScalarValue,
@@ -1227,14 +1227,14 @@ impl<'r, S: 'r> Registry<'r, S> {
         Argument::new(name, self.get_type::<T>(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<'static>) {
         self.types
             .entry(name)
             .or_insert(MetaType::Placeholder(PlaceholderMeta { of_type }));
     }
 
     /// Creates a [`ScalarMeta`] type.
-    pub fn build_scalar_type<T>(&mut self, info: &T::TypeInfo) -> ScalarMeta<'r, S>
+    pub fn build_scalar_type<T>(&mut self, info: &T::TypeInfo) -> ScalarMeta<S>
     where
         T: GraphQLType<S> + FromInputValue<S> + ParseScalarValue<S>,
         T::Error: IntoFieldError<S>,
@@ -1242,7 +1242,7 @@ impl<'r, S: 'r> Registry<'r, S> {
     {
         let name = T::name(info).expect("Scalar types must be named. Implement `name()`");
 
-        ScalarMeta::new::<T>(Cow::Owned(name.into()))
+        ScalarMeta::new::<T>(name)
     }
 
     /// Creates a [`ListMeta`] type.
@@ -1253,7 +1253,7 @@ impl<'r, S: 'r> Registry<'r, S> {
         &mut self,
         info: &T::TypeInfo,
         expected_size: Option<usize>,
-    ) -> ListMeta<'r>
+    ) -> ListMeta
     where
         T: GraphQLType<S> + ?Sized,
         S: ScalarValue,
@@ -1263,7 +1263,7 @@ impl<'r, S: 'r> Registry<'r, S> {
     }
 
     /// Creates a [`NullableMeta`] type.
-    pub fn build_nullable_type<T>(&mut self, info: &T::TypeInfo) -> NullableMeta<'r>
+    pub fn build_nullable_type<T>(&mut self, info: &T::TypeInfo) -> NullableMeta
     where
         T: GraphQLType<S> + ?Sized,
         S: ScalarValue,
@@ -1273,11 +1273,7 @@ impl<'r, S: 'r> Registry<'r, S> {
     }
 
     /// Creates an [`ObjectMeta`] type with the given `fields`.
-    pub fn build_object_type<T>(
-        &mut self,
-        info: &T::TypeInfo,
-        fields: &[Field<'r, S>],
-    ) -> ObjectMeta<'r, S>
+    pub fn build_object_type<T>(&mut self, info: &T::TypeInfo, fields: &[Field<S>]) -> ObjectMeta<S>
     where
         T: GraphQLType<S> + ?Sized,
         S: ScalarValue,
@@ -1285,16 +1281,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::<String>("__typename", &()));
-        ObjectMeta::new(Cow::Owned(name.into()), &v)
+        v.push(self.field::<String>(arcstr::literal!("__typename"), &()));
+        ObjectMeta::new(name, &v)
     }
 
     /// Creates an [`EnumMeta`] type out of the provided `values`.
-    pub fn build_enum_type<T>(
-        &mut self,
-        info: &T::TypeInfo,
-        values: &[EnumValue],
-    ) -> EnumMeta<'r, S>
+    pub fn build_enum_type<T>(&mut self, info: &T::TypeInfo, values: &[EnumValue]) -> EnumMeta<S>
     where
         T: GraphQLType<S> + FromInputValue<S>,
         T::Error: IntoFieldError<S>,
@@ -1302,15 +1294,15 @@ impl<'r, S: 'r> Registry<'r, S> {
     {
         let name = T::name(info).expect("Enum types must be named. Implement `name()`");
 
-        EnumMeta::new::<T>(Cow::Owned(name.into()), values)
+        EnumMeta::new::<T>(name, values)
     }
 
     /// Creates an [`InterfaceMeta`] type with the given `fields`.
     pub fn build_interface_type<T>(
         &mut self,
         info: &T::TypeInfo,
-        fields: &[Field<'r, S>],
-    ) -> InterfaceMeta<'r, S>
+        fields: &[Field<S>],
+    ) -> InterfaceMeta<S>
     where
         T: GraphQLType<S> + ?Sized,
         S: ScalarValue,
@@ -1318,27 +1310,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::<String>("__typename", &()));
-        InterfaceMeta::new(Cow::Owned(name.into()), &v)
+        v.push(self.field::<String>(arcstr::literal!("__typename"), &()));
+        InterfaceMeta::new(name, &v)
     }
 
     /// Creates an [`UnionMeta`] type of the given `types`.
-    pub fn build_union_type<T>(&mut self, info: &T::TypeInfo, types: &[Type<'r>]) -> UnionMeta<'r>
+    pub fn build_union_type<T>(&mut self, info: &T::TypeInfo, types: &[Type<'static>]) -> UnionMeta
     where
         T: GraphQLType<S> + ?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<T>(
         &mut self,
         info: &T::TypeInfo,
-        args: &[Argument<'r, S>],
-    ) -> InputObjectMeta<'r, S>
+        args: &[Argument<S>],
+    ) -> InputObjectMeta<S>
     where
         T: GraphQLType<S> + FromInputValue<S>,
         T::Error: IntoFieldError<S>,
@@ -1346,6 +1338,6 @@ impl<'r, S: 'r> Registry<'r, S> {
     {
         let name = T::name(info).expect("Input object types must be named. Implement name()");
 
-        InputObjectMeta::new::<T>(Cow::Owned(name.into()), args)
+        InputObjectMeta::new::<T>(name, args)
     }
 }
diff --git a/juniper/src/executor/owned_executor.rs b/juniper/src/executor/owned_executor.rs
index cce1a208e..8da2205a2 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<Vec<Selection<'a, S>>>,
     pub(super) parent_selection_set: Option<Vec<Selection<'a, S>>>,
     pub(super) current_type: TypeType<'a, S>,
-    pub(super) schema: &'a SchemaType<'a, S>,
+    pub(super) schema: &'a SchemaType<S>,
     pub(super) context: &'a CtxT,
     pub(super) errors: RwLock<Vec<ExecutionError<S>>>,
     pub(super) field_path: Arc<FieldPath<'a>>,
diff --git a/juniper/src/http/mod.rs b/juniper/src/http/mod.rs
index 38ef764f2..a8a47837a 100644
--- a/juniper/src/http/mod.rs
+++ b/juniper/src/http/mod.rs
@@ -110,7 +110,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<QueryT, MutationT, SubscriptionT, S>,
         context: &'a QueryT::Context,
     ) -> GraphQLResponse<S>
     where
@@ -136,7 +136,7 @@ where
 /// level of this crate.
 pub async fn resolve_into_stream<'req, 'rn, 'ctx, 'a, QueryT, MutationT, SubscriptionT, S>(
     req: &'req GraphQLRequest<S>,
-    root_node: &'rn RootNode<'a, QueryT, MutationT, SubscriptionT, S>,
+    root_node: &'rn RootNode<QueryT, MutationT, SubscriptionT, S>,
     context: &'ctx QueryT::Context,
 ) -> Result<(Value<ValuesStream<'a, S>>, Vec<ExecutionError<S>>), GraphQLError>
 where
@@ -296,7 +296,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<QueryT, MutationT, SubscriptionT, S>,
         context: &'a QueryT::Context,
     ) -> GraphQLBatchResponse<S>
     where
diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs
index 7b8bc4f73..7f949945d 100644
--- a/juniper/src/lib.rs
+++ b/juniper/src/lib.rs
@@ -18,6 +18,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.
@@ -193,7 +195,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<QueryT, MutationT, SubscriptionT, S>,
     variables: &Variables<S>,
     context: &QueryT::Context,
 ) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError>
@@ -244,7 +246,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<QueryT, MutationT, SubscriptionT, S>,
     variables: &Variables<S>,
     context: &'a QueryT::Context,
 ) -> Result<(Value<ValuesStream<'a, S>>, Vec<ExecutionError<S>>), GraphQLError>
diff --git a/juniper/src/parser/document.rs b/juniper/src/parser/document.rs
index 4ace75abc..90d4dbee5 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<S>,
 ) -> UnlocatedParseResult<OwnedDocument<'a, S>>
 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<S>,
 ) -> UnlocatedParseResult<OwnedDocument<'a, S>>
 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<S>,
 ) -> UnlocatedParseResult<Definition<'a, S>>
 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<S>,
 ) -> ParseResult<Operation<'a, S>>
 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<S>,
 ) -> ParseResult<Fragment<'a, S>>
 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<S>,
+    fields: Option<&[&MetaField<S>]>,
 ) -> OptionParseResult<Vec<Selection<'a, S>>>
 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<S>,
+    fields: Option<&[&MetaField<S>]>,
 ) -> ParseResult<Vec<Selection<'a, S>>>
 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<S>,
+    fields: Option<&[&MetaField<S>]>,
 ) -> UnlocatedParseResult<Selection<'a, S>>
 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<S>,
+    fields: Option<&[&MetaField<S>]>,
 ) -> UnlocatedParseResult<Selection<'a, S>>
 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<S>,
+    fields: Option<&[&MetaField<S>]>,
 ) -> ParseResult<Field<'a, S>>
 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<S>,
+    arguments: Option<&[Argument<S>]>,
 ) -> OptionParseResult<Arguments<'a, S>>
 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<S>,
+    arguments: Option<&[Argument<S>]>,
 ) -> ParseResult<(Spanning<&'a str>, Spanning<InputValue<S>>)>
 where
     S: ScalarValue,
@@ -400,9 +398,9 @@ fn parse_operation_type(parser: &mut Parser<'_>) -> ParseResult<OperationType> {
     }
 }
 
-fn parse_variable_definitions<'a, 'b, S>(
+fn parse_variable_definitions<'a, S>(
     parser: &mut Parser<'a>,
-    schema: &'b SchemaType<'b, S>,
+    schema: &SchemaType<S>,
 ) -> OptionParseResult<VariableDefinitions<'a, S>>
 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<S>,
 ) -> 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<S>,
 ) -> OptionParseResult<Vec<Spanning<Directive<'a, S>>>>
 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<S>,
 ) -> ParseResult<Directive<'a, S>>
 where
     S: ScalarValue,
@@ -523,7 +521,7 @@ pub fn parse_type<'a>(parser: &mut Parser<'a>) -> ParseResult<Type<'a>> {
             Type::List(Box::new(inner_type.item), None),
         )
     } else {
-        parser.expect_name()?.map(|s| Type::Named(Cow::Borrowed(s)))
+        parser.expect_name()?.map(|n| Type::Named(n.into()))
     };
 
     Ok(match *parser.peek() {
@@ -541,7 +539,7 @@ fn wrap_non_null<'a>(parser: &mut Parser<'a>, inner: Spanning<Type<'a>>) -> Pars
     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/parser.rs b/juniper/src/parser/parser.rs
index f11facc33..b679580d5 100644
--- a/juniper/src/parser/parser.rs
+++ b/juniper/src/parser/parser.rs
@@ -1,7 +1,5 @@
 use std::{error::Error, fmt};
 
-use smartstring::alias::String;
-
 use crate::parser::{Lexer, LexerError, Spanning, Token};
 
 /// Error while parsing a GraphQL query
diff --git a/juniper/src/parser/tests/value.rs b/juniper/src/parser/tests/value.rs
index cda48e0d7..f20c24f03 100644
--- a/juniper/src/parser/tests/value.rs
+++ b/juniper/src/parser/tests/value.rs
@@ -57,7 +57,7 @@ where
     T: FromInputValue<DefaultScalarValue> + ParseScalarValue<DefaultScalarValue>,
     T::Error: IntoFieldError,
 {
-    MetaType::Scalar(ScalarMeta::new::<T>(name.into()))
+    MetaType::Scalar(ScalarMeta::new::<T>(name))
 }
 
 fn parse_value<S>(s: &str, meta: &MetaType<S>) -> Spanning<InputValue<S>>
@@ -116,7 +116,7 @@ fn input_value_literals() {
         ),
     );
     let values = &[EnumValue::new("enum_value")];
-    let e: EnumMeta<DefaultScalarValue> = EnumMeta::new::<Enum>("TestEnum".into(), values);
+    let e: EnumMeta<DefaultScalarValue> = EnumMeta::new::<Enum>("TestEnum", values);
 
     assert_eq!(
         parse_value::<DefaultScalarValue>("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>("foo".into(), &fields));
+    let meta = &MetaType::InputObject(InputObjectMeta::new::<Foo>("foo", &fields));
     assert_eq!(
         parse_value::<DefaultScalarValue>("{}", 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<S>(
     parser: &mut Parser<'_>,
     is_const: bool,
-    schema: &'b SchemaType<'b, S>,
-    tpe: Option<&MetaType<'b, S>>,
+    schema: &SchemaType<S>,
+    tpe: Option<&MetaType<S>>,
 ) -> ParseResult<InputValue<S>>
 where
     S: ScalarValue,
@@ -117,11 +117,11 @@ where
     }
 }
 
-fn parse_list_literal<'b, S>(
+fn parse_list_literal<S>(
     parser: &mut Parser<'_>,
     is_const: bool,
-    schema: &'b SchemaType<'b, S>,
-    tpe: Option<&MetaType<'b, S>>,
+    schema: &SchemaType<S>,
+    tpe: Option<&MetaType<S>>,
 ) -> ParseResult<InputValue<S>>
 where
     S: ScalarValue,
@@ -135,11 +135,11 @@ where
         .map(InputValue::parsed_list))
 }
 
-fn parse_object_literal<'b, S>(
+fn parse_object_literal<S>(
     parser: &mut Parser<'_>,
     is_const: bool,
-    schema: &'b SchemaType<'b, S>,
-    object_tpe: Option<&InputObjectMeta<'b, S>>,
+    schema: &SchemaType<S>,
+    object_tpe: Option<&InputObjectMeta<S>>,
 ) -> ParseResult<InputValue<S>>
 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<S>(
     parser: &mut Parser<'_>,
     is_const: bool,
-    schema: &'b SchemaType<'b, S>,
-    object_meta: Option<&InputObjectMeta<'b, S>>,
+    schema: &SchemaType<S>,
+    object_meta: Option<&InputObjectMeta<S>>,
 ) -> ParseResult<(Spanning<String>, Spanning<InputValue<S>>)>
 where
     S: ScalarValue,
@@ -197,10 +197,10 @@ where
     ))
 }
 
-fn parse_scalar_literal_by_infered_type<'b, S>(
+fn parse_scalar_literal_by_infered_type<S>(
     token: ScalarToken<'_>,
     span: Span,
-    schema: &'b SchemaType<'b, S>,
+    schema: &SchemaType<S>,
 ) -> ParseResult<InputValue<S>>
 where
     S: ScalarValue,
diff --git a/juniper/src/schema/meta.rs b/juniper/src/schema/meta.rs
index f7673cd9d..be80aaf8c 100644
--- a/juniper/src/schema/meta.rs
+++ b/juniper/src/schema/meta.rs
@@ -1,7 +1,8 @@
 //! Types used to describe a `GraphQL` schema
 
-use juniper::IntoFieldError;
-use std::{borrow::Cow, fmt};
+use std::fmt;
+
+use arcstr::ArcStr;
 
 use crate::{
     ast::{FromInputValue, InputValue, Type},
@@ -9,7 +10,7 @@ use crate::{
     schema::model::SchemaType,
     types::base::TypeKind,
     value::{DefaultScalarValue, ParseScalarValue},
-    FieldError,
+    FieldError, IntoFieldError,
 };
 
 /// Whether an item is deprecated, with context.
@@ -18,428 +19,58 @@ pub enum DeprecationStatus {
     /// The field/variant is not deprecated.
     Current,
     /// The field/variant is deprecated, with an optional reason
-    Deprecated(Option<String>),
+    Deprecated(Option<ArcStr>),
 }
 
 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<S> {
     #[doc(hidden)]
-    pub name: Cow<'a, str>,
+    pub name: ArcStr,
     #[doc(hidden)]
-    pub description: Option<String>,
+    pub description: Option<ArcStr>,
     #[doc(hidden)]
-    pub specified_by_url: Option<Cow<'a, str>>,
+    pub specified_by_url: Option<ArcStr>,
     pub(crate) try_parse_fn: InputValueParseFn<S>,
     pub(crate) parse_fn: ScalarTokenParseFn<S>,
 }
 
-/// Shortcut for an [`InputValue`] parsing function.
-pub type InputValueParseFn<S> = for<'b> fn(&'b InputValue<S>) -> Result<(), FieldError<S>>;
-
-/// Shortcut for a [`ScalarToken`] parsing function.
-pub type ScalarTokenParseFn<S> = for<'b> fn(ScalarToken<'b>) -> Result<S, ParseError>;
-
-/// List type metadata
-#[derive(Debug)]
-pub struct ListMeta<'a> {
-    #[doc(hidden)]
-    pub of_type: Type<'a>,
-
-    #[doc(hidden)]
-    pub expected_size: Option<usize>,
-}
-
-/// 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<String>,
-    #[doc(hidden)]
-    pub fields: Vec<Field<'a, S>>,
-    #[doc(hidden)]
-    pub interface_names: Vec<String>,
-}
-
-/// Enum type metadata
-pub struct EnumMeta<'a, S> {
-    #[doc(hidden)]
-    pub name: Cow<'a, str>,
-    #[doc(hidden)]
-    pub description: Option<String>,
-    #[doc(hidden)]
-    pub values: Vec<EnumValue>,
-    pub(crate) try_parse_fn: InputValueParseFn<S>,
-}
-
-/// Interface type metadata
-#[derive(Debug)]
-pub struct InterfaceMeta<'a, S> {
-    #[doc(hidden)]
-    pub name: Cow<'a, str>,
-    #[doc(hidden)]
-    pub description: Option<String>,
-    #[doc(hidden)]
-    pub fields: Vec<Field<'a, S>>,
-    #[doc(hidden)]
-    pub interface_names: Vec<String>,
-}
-
-/// Union type metadata
-#[derive(Debug)]
-pub struct UnionMeta<'a> {
-    #[doc(hidden)]
-    pub name: Cow<'a, str>,
-    #[doc(hidden)]
-    pub description: Option<String>,
-    #[doc(hidden)]
-    pub of_type_names: Vec<String>,
-}
-
-/// Input object metadata
-pub struct InputObjectMeta<'a, S> {
-    #[doc(hidden)]
-    pub name: Cow<'a, str>,
-    #[doc(hidden)]
-    pub description: Option<String>,
-    #[doc(hidden)]
-    pub input_fields: Vec<Argument<'a, S>>,
-    pub(crate) try_parse_fn: InputValueParseFn<S>,
-}
-
-/// 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<String>,
-    #[doc(hidden)]
-    pub arguments: Option<Vec<Argument<'a, S>>>,
-    #[doc(hidden)]
-    pub field_type: Type<'a>,
-    #[doc(hidden)]
-    pub deprecation_status: DeprecationStatus,
-}
-
-impl<'a, S> Field<'a, 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<String>,
-    #[doc(hidden)]
-    pub arg_type: Type<'a>,
-    #[doc(hidden)]
-    pub default_value: Option<InputValue<S>>,
-}
-
-impl<'a, S> Argument<'a, 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<String>,
-    /// 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<S>> {
-        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<S>> {
-        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<InputValueParseFn<S>> {
-        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<S>) -> Option<Vec<&'b Field<'b, S>>> {
-        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<S: fmt::Debug> 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)
+            .field("specified_by_url", &self.specified_by_url)
+            .finish_non_exhaustive()
     }
 }
 
-impl<'a, S> ScalarMeta<'a, S> {
+impl<S> ScalarMeta<S> {
     /// Builds a new [`ScalarMeta`] type with the specified `name`.
-    pub fn new<T>(name: Cow<'a, str>) -> Self
+    pub fn new<T>(name: impl Into<ArcStr>) -> Self
     where
         T: FromInputValue<S> + ParseScalarValue<S>,
         T::Error: IntoFieldError<S>,
     {
         Self {
-            name,
+            name: name.into(),
             description: None,
             specified_by_url: None,
             try_parse_fn: try_parse_fn::<S, T>,
@@ -451,7 +82,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<ArcStr>) -> Self {
         self.description = Some(description.into());
         self
     }
@@ -462,23 +93,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<Cow<'a, str>>) -> Self {
+    pub fn specified_by_url(mut self, url: impl Into<ArcStr>) -> 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<S> {
         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<S> = for<'b> fn(&'b InputValue<S>) -> Result<(), FieldError<S>>;
+
+/// Shortcut for a [`ScalarToken`] parsing function.
+pub type ScalarTokenParseFn<S> = for<'b> fn(ScalarToken<'b>) -> Result<S, ParseError>;
+
+/// List type metadata
+#[derive(Debug)]
+pub struct ListMeta {
+    #[doc(hidden)]
+    pub of_type: Type<'static>,
+
+    #[doc(hidden)]
+    pub expected_size: Option<usize>,
+}
+
+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<usize>) -> Self {
+    /// Specifying `expected_size` will be used to ensure that values of this type will always match
+    /// it.
+    pub fn new(of_type: Type<'static>, expected_size: Option<usize>) -> Self {
         Self {
             of_type,
             expected_size,
@@ -486,31 +133,51 @@ impl<'a> ListMeta<'a> {
     }
 
     /// Wraps this [`ListMeta`] type into a generic [`MetaType`].
-    pub fn into_meta<S>(self) -> MetaType<'a, S> {
+    pub fn into_meta<S>(self) -> MetaType<S> {
         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<'static>,
+}
+
+impl NullableMeta {
+    /// Builds a new [`NullableMeta`] type by wrapping the specified [`Type`].
+    pub fn new(of_type: Type<'static>) -> Self {
         Self { of_type }
     }
 
     /// Wraps this [`NullableMeta`] type into a generic [`MetaType`].
-    pub fn into_meta<S>(self) -> MetaType<'a, S> {
+    pub fn into_meta<S>(self) -> MetaType<S> {
         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<S> {
+    #[doc(hidden)]
+    pub name: ArcStr,
+    #[doc(hidden)]
+    pub description: Option<ArcStr>,
+    #[doc(hidden)]
+    pub fields: Vec<Field<S>>,
+    #[doc(hidden)]
+    pub interface_names: Vec<ArcStr>,
+}
+
+impl<S> ObjectMeta<S> {
+    /// Builds a new [`ObjectMeta`] type with the specified `name` and `fields`.
+    pub fn new(name: impl Into<ArcStr>, fields: &[Field<S>]) -> Self
     where
         S: Clone,
     {
         Self {
-            name,
+            name: name.into(),
             description: None,
             fields: fields.to_vec(),
             interface_names: vec![],
@@ -521,39 +188,59 @@ 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<ArcStr>) -> 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<'static>]) -> Self {
         self.interface_names = interfaces
             .iter()
-            .map(|t| t.innermost_name().into())
+            .map(|t| t.innermost_name().to_owned())
             .collect();
         self
     }
 
     /// Wraps this [`ObjectMeta`] type into a generic [`MetaType`].
-    pub fn into_meta(self) -> MetaType<'a, S> {
+    pub fn into_meta(self) -> MetaType<S> {
         MetaType::Object(self)
     }
 }
 
-impl<'a, S> EnumMeta<'a, S> {
-    /// Build a new [`EnumMeta`] type with the specified `name` and possible
-    /// `values`.
-    pub fn new<T>(name: Cow<'a, str>, values: &[EnumValue]) -> Self
+/// Enum type metadata
+pub struct EnumMeta<S> {
+    #[doc(hidden)]
+    pub name: ArcStr,
+    #[doc(hidden)]
+    pub description: Option<ArcStr>,
+    #[doc(hidden)]
+    pub values: Vec<EnumValue>,
+    pub(crate) try_parse_fn: InputValueParseFn<S>,
+}
+
+impl<S: fmt::Debug> 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_non_exhaustive()
+    }
+}
+
+impl<S> EnumMeta<S> {
+    /// Builds a new [`EnumMeta`] type with the specified `name` and possible `values`.
+    pub fn new<T>(name: impl Into<ArcStr>, values: &[EnumValue]) -> Self
     where
         T: FromInputValue<S>,
         T::Error: IntoFieldError<S>,
     {
         Self {
-            name,
+            name: name.into(),
             description: None,
             values: values.to_owned(),
             try_parse_fn: try_parse_fn::<S, T>,
@@ -564,26 +251,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<ArcStr>) -> 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<S> {
         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<S> {
+    #[doc(hidden)]
+    pub name: ArcStr,
+    #[doc(hidden)]
+    pub description: Option<ArcStr>,
+    #[doc(hidden)]
+    pub fields: Vec<Field<S>>,
+    #[doc(hidden)]
+    pub interface_names: Vec<ArcStr>,
+}
+
+impl<S> InterfaceMeta<S> {
+    /// Builds a new [`InterfaceMeta`] type with the specified `name` and `fields`.
+    pub fn new(name: impl Into<ArcStr>, fields: &[Field<S>]) -> Self
     where
         S: Clone,
     {
         Self {
-            name,
+            name: name.into(),
             description: None,
             fields: fields.to_vec(),
             interface_names: Vec::new(),
@@ -594,7 +293,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<ArcStr>) -> Self {
         self.description = Some(description.into());
         self
     }
@@ -603,28 +302,41 @@ 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<'static>]) -> Self {
         self.interface_names = interfaces
             .iter()
-            .map(|t| t.innermost_name().into())
+            .map(|t| t.innermost_name().to_owned())
             .collect();
         self
     }
 
     /// Wraps this [`InterfaceMeta`] type into a generic [`MetaType`].
-    pub fn into_meta(self) -> MetaType<'a, S> {
+    pub fn into_meta(self) -> MetaType<S> {
         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<ArcStr>,
+    #[doc(hidden)]
+    pub of_type_names: Vec<ArcStr>,
+}
+
+impl UnionMeta {
+    /// Builds a new [`UnionMeta`] type with the specified `name` and possible [`Type`]s.
+    pub fn new(name: impl Into<ArcStr>, of_types: &[Type<'static>]) -> Self {
         Self {
-            name,
+            name: name.into(),
             description: None,
-            of_type_names: of_types.iter().map(|t| t.innermost_name().into()).collect(),
+            of_type_names: of_types
+                .iter()
+                .map(|t| t.innermost_name().to_owned())
+                .collect(),
         }
     }
 
@@ -632,55 +344,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<ArcStr>) -> Self {
         self.description = Some(description.into());
         self
     }
 
     /// Wraps this [`UnionMeta`] type into a generic [`MetaType`].
-    pub fn into_meta<S>(self) -> MetaType<'a, S> {
+    pub fn into_meta<S>(self) -> MetaType<S> {
         MetaType::Union(self)
     }
 }
 
-impl<'a, S> InputObjectMeta<'a, S> {
-    /// Builds a new [`InputObjectMeta`] type with the specified `name` and
-    /// `input_fields`.
-    pub fn new<T>(name: Cow<'a, str>, input_fields: &[Argument<'a, S>]) -> Self
+/// Input object metadata
+pub struct InputObjectMeta<S> {
+    #[doc(hidden)]
+    pub name: ArcStr,
+    #[doc(hidden)]
+    pub description: Option<ArcStr>,
+    #[doc(hidden)]
+    pub input_fields: Vec<Argument<S>>,
+    pub(crate) try_parse_fn: InputValueParseFn<S>,
+}
+
+impl<S: fmt::Debug> 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_non_exhaustive()
+    }
+}
+
+impl<S> InputObjectMeta<S> {
+    /// Builds a new [`InputObjectMeta`] type with the specified `name` and `input_fields`.
+    pub fn new<T>(name: impl Into<ArcStr>, input_fields: &[Argument<S>]) -> Self
     where
         T: FromInputValue<S>,
         T::Error: IntoFieldError<S>,
         S: Clone,
     {
         Self {
-            name,
+            name: name.into(),
             description: None,
             input_fields: input_fields.to_vec(),
             try_parse_fn: try_parse_fn::<S, T>,
         }
     }
 
-    /// 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<ArcStr>) -> 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<S> {
         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<'static>,
+}
+
+/// Metadata for a field
+#[derive(Debug, Clone)]
+pub struct Field<S> {
+    #[doc(hidden)]
+    pub name: ArcStr,
+    #[doc(hidden)]
+    pub description: Option<ArcStr>,
+    #[doc(hidden)]
+    pub arguments: Option<Vec<Argument<S>>>,
+    #[doc(hidden)]
+    pub field_type: Type<'static>,
+    #[doc(hidden)]
+    pub deprecation_status: DeprecationStatus,
+}
+
+impl<S> Field<S> {
+    /// 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<ArcStr>) -> Self {
         self.description = Some(description.into());
         self
     }
@@ -689,7 +446,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<S>) -> Self {
         match self.arguments {
             None => {
                 self.arguments = Some(vec![argument]);
@@ -701,19 +458,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<impl Into<ArcStr>>) -> 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<S> {
+    #[doc(hidden)]
+    pub name: ArcStr,
+    #[doc(hidden)]
+    pub description: Option<ArcStr>,
+    #[doc(hidden)]
+    pub arg_type: Type<'static>,
+    #[doc(hidden)]
+    pub default_value: Option<InputValue<S>>,
+}
+
+impl<S> Argument<S> {
     /// 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<ArcStr>, arg_type: Type<'static>) -> Self {
         Self {
             name: name.into(),
             description: None,
@@ -726,12 +503,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<ArcStr>) -> 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 +525,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<ArcStr>,
+
+    /// 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<ArcStr>) -> Self {
         Self {
             name: name.into(),
             description: None,
@@ -755,7 +557,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<ArcStr>) -> Self {
         self.description = Some(description.into());
         self
     }
@@ -764,38 +566,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<impl Into<ArcStr>>) -> Self {
         self.deprecation_status = DeprecationStatus::Deprecated(reason.map(Into::into));
         self
     }
 }
 
-impl<'a, S: fmt::Debug> fmt::Debug for ScalarMeta<'a, 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<S = DefaultScalarValue> {
+    #[doc(hidden)]
+    Scalar(ScalarMeta<S>),
+    #[doc(hidden)]
+    List(ListMeta),
+    #[doc(hidden)]
+    Nullable(NullableMeta),
+    #[doc(hidden)]
+    Object(ObjectMeta<S>),
+    #[doc(hidden)]
+    Enum(EnumMeta<S>),
+    #[doc(hidden)]
+    Interface(InterfaceMeta<S>),
+    #[doc(hidden)]
+    Union(UnionMeta),
+    #[doc(hidden)]
+    InputObject(InputObjectMeta<S>),
+    #[doc(hidden)]
+    Placeholder(PlaceholderMeta),
 }
 
-impl<'a, S: fmt::Debug> fmt::Debug for EnumMeta<'a, 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<S> MetaType<S> {
+    /// 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<'a, S: fmt::Debug> fmt::Debug for InputObjectMeta<'a, 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<S>> {
+        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<S>> {
+        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<'static> {
+        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().into()),
+            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<InputValueParseFn<S>> {
+        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<S>) -> Option<Vec<&'s Field<S>>> {
+        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 +829,6 @@ where
     T::Error: IntoFieldError<S>,
 {
     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 75b216a7a..a06b88f4f 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<S>,
     MutationT: GraphQLType<S>,
     SubscriptionT: GraphQLType<S>,
@@ -40,64 +40,13 @@ pub struct RootNode<
     #[doc(hidden)]
     pub subscription_info: SubscriptionT::TypeInfo,
     #[doc(hidden)]
-    pub schema: SchemaType<'a, S>,
+    pub schema: SchemaType<S>,
     #[doc(hidden)]
     pub introspection_disabled: bool,
 }
 
-/// Metadata for a schema
-#[derive(Debug)]
-pub struct SchemaType<'a, S> {
-    pub(crate) description: Option<Cow<'a, str>>,
-    pub(crate) types: FnvHashMap<Name, MetaType<'a, S>>,
-    pub(crate) query_type_name: String,
-    pub(crate) mutation_type_name: Option<String>,
-    pub(crate) subscription_type_name: Option<String>,
-    directives: FnvHashMap<String, DirectiveType<'a, S>>,
-}
-
-impl<'a, S> Context for SchemaType<'a, S> {}
-
-#[derive(Clone)]
-pub enum TypeType<'a, S: 'a> {
-    Concrete(&'a MetaType<'a, S>),
-    NonNull(Box<TypeType<'a, S>>),
-    List(Box<TypeType<'a, S>>, Option<usize>),
-}
-
-#[derive(Debug)]
-pub struct DirectiveType<'a, S> {
-    pub name: String,
-    pub description: Option<String>,
-    pub locations: Vec<DirectiveLocation>,
-    pub arguments: Vec<Argument<'a, S>>,
-    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<'a, QueryT, MutationT, SubscriptionT>
-    RootNode<'a, QueryT, MutationT, SubscriptionT, DefaultScalarValue>
+impl<QueryT, MutationT, SubscriptionT>
+    RootNode<QueryT, MutationT, SubscriptionT, DefaultScalarValue>
 where
     QueryT: GraphQLType<DefaultScalarValue, TypeInfo = ()>,
     MutationT: GraphQLType<DefaultScalarValue, TypeInfo = ()>,
@@ -110,9 +59,9 @@ where
     }
 }
 
-impl<'a, QueryT, MutationT, SubscriptionT, S> RootNode<'a, QueryT, MutationT, SubscriptionT, S>
+impl<QueryT, MutationT, SubscriptionT, S> RootNode<QueryT, MutationT, SubscriptionT, S>
 where
-    S: ScalarValue + 'a,
+    S: ScalarValue,
     QueryT: GraphQLType<S, TypeInfo = ()>,
     MutationT: GraphQLType<S, TypeInfo = ()>,
     SubscriptionT: GraphQLType<S, TypeInfo = ()>,
@@ -128,12 +77,12 @@ where
     }
 }
 
-impl<'a, S, QueryT, MutationT, SubscriptionT> RootNode<'a, QueryT, MutationT, SubscriptionT, S>
+impl<S, QueryT, MutationT, SubscriptionT> RootNode<QueryT, MutationT, SubscriptionT, S>
 where
     QueryT: GraphQLType<S>,
     MutationT: GraphQLType<S>,
     SubscriptionT: GraphQLType<S>,
-    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<Query, EmptyMutation, EmptySubscription>;
     ///
     /// 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::{
             graphql_parser::GraphQLParserTranslator, SchemaTranslator as _,
         };
@@ -256,7 +205,20 @@ where
     }
 }
 
-impl<'a, S> SchemaType<'a, S> {
+/// Metadata for a schema
+#[derive(Debug)]
+pub struct SchemaType<S> {
+    pub(crate) description: Option<ArcStr>,
+    pub(crate) types: FnvHashMap<Name, MetaType<S>>,
+    pub(crate) query_type_name: String,
+    pub(crate) mutation_type_name: Option<String>,
+    pub(crate) subscription_type_name: Option<String>,
+    directives: FnvHashMap<ArcStr, DirectiveType<S>>,
+}
+
+impl<S> Context for SchemaType<S> {}
+
+impl<S> SchemaType<S> {
     /// Create a new schema.
     pub fn new<QueryT, MutationT, SubscriptionT>(
         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<S>,
         MutationT: GraphQLType<S>,
         SubscriptionT: GraphQLType<S>,
@@ -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<str> = registry
             .get_type::<QueryT>(query_info)
             .innermost_name()
-            .to_owned();
-        let mutation_type_name = registry
+            .into();
+        let mutation_type_name: Box<str> = registry
             .get_type::<MutationT>(mutation_info)
             .innermost_name()
-            .to_owned();
-        let subscription_type_name = registry
+            .into();
+        let subscription_type_name: Box<str> = registry
             .get_type::<SubscriptionT>(subscription_info)
             .innermost_name()
-            .to_owned();
+            .into();
 
         registry.get_type::<SchemaType<S>>(&());
 
-        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::<SchemaType<S>>("__schema", &()),
+            registry.field::<SchemaType<S>>(arcstr::literal!("__schema"), &()),
             registry
-                .field::<TypeType<S>>("__type", &())
-                .argument(registry.arg::<String>("name", &())),
+                .field::<TypeType<S>>(arcstr::literal!("__type"), &())
+                .argument(registry.arg::<String>(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,12 +299,12 @@ impl<'a, S> SchemaType<'a, S> {
     }
 
     /// Add a description.
-    pub fn set_description(&mut self, description: impl Into<Cow<'a, str>>) {
-        self.description = Some(description.into());
+    pub fn set_description(&mut self, description: ArcStr) {
+        self.description = Some(description);
     }
 
     /// 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<S>) {
         self.directives.insert(directive.name.clone(), directive);
     }
 
@@ -358,12 +318,10 @@ impl<'a, S> SchemaType<'a, S> {
         self.types.get(name)
     }
 
-    pub(crate) fn lookup_type(&self, tpe: &Type) -> Option<&MetaType<S>> {
-        match *tpe {
-            Type::NonNullNamed(ref name) | Type::Named(ref name) => {
-                self.concrete_type_by_name(name)
-            }
-            Type::List(ref inner, _) | Type::NonNullList(ref inner, _) => self.lookup_type(inner),
+    pub(crate) fn lookup_type(&self, tpe: &Type<'_>) -> Option<&MetaType<S>> {
+        match tpe {
+            Type::Named(name) | Type::NonNullNamed(name) => self.concrete_type_by_name(name),
+            Type::List(inner, ..) | Type::NonNullList(inner, ..) => self.lookup_type(inner),
         }
     }
 
@@ -371,7 +329,7 @@ impl<'a, S> SchemaType<'a, S> {
     pub fn query_type(&self) -> TypeType<S> {
         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 +337,7 @@ impl<'a, S> SchemaType<'a, S> {
     /// Get the concrete query type from the schema.
     pub fn concrete_query_type(&self) -> &MetaType<S> {
         self.types
-            .get(&self.query_type_name)
+            .get(self.query_type_name.as_str())
             .expect("Query type does not exist in schema")
     }
 
@@ -432,18 +390,19 @@ impl<'a, S> SchemaType<'a, S> {
     }
 
     /// Make a type.
-    pub fn make_type(&self, t: &Type) -> TypeType<S> {
-        match *t {
-            Type::NonNullNamed(ref n) => TypeType::NonNull(Box::new(
+    pub fn make_type(&self, ty: &Type<'_>) -> TypeType<S> {
+        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).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).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)
-            }
         }
     }
 
@@ -512,22 +471,20 @@ 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(&self, sub_type: &Type<'_>, super_type: &Type<'_>) -> bool {
         if super_type == sub_type {
             return true;
         }
 
         match (super_type, sub_type) {
-            (&NonNullNamed(ref super_name), &NonNullNamed(ref sub_name))
-            | (&Named(ref super_name), &Named(ref sub_name))
-            | (&Named(ref super_name), &NonNullNamed(ref sub_name)) => {
+            (Type::NonNullNamed(super_name), Type::NonNullNamed(sub_name))
+            | (Type::Named(super_name), Type::Named(sub_name))
+            | (Type::Named(super_name), Type::NonNullNamed(sub_name)) => {
                 self.is_named_subtype(sub_name, super_name)
             }
-            (&NonNullList(ref super_inner, _), &NonNullList(ref sub_inner, _))
-            | (&List(ref super_inner, _), &List(ref sub_inner, _))
-            | (&List(ref super_inner, _), &NonNullList(ref sub_inner, _)) => {
+            (Type::NonNullList(super_inner, ..), Type::NonNullList(sub_inner, ..))
+            | (Type::List(super_inner, ..), Type::List(sub_inner, ..))
+            | (Type::List(super_inner, ..), Type::NonNullList(sub_inner, ..)) => {
                 self.is_subtype(sub_inner, super_inner)
             }
             _ => false,
@@ -549,48 +506,70 @@ impl<'a, S> SchemaType<'a, S> {
     }
 }
 
+#[derive(Clone)]
+pub enum TypeType<'a, S: 'a> {
+    Concrete(&'a MetaType<S>),
+    NonNull(Box<TypeType<'a, S>>),
+    List(Box<TypeType<'a, S>>, Option<usize>),
+}
+
+impl<'a, S> fmt::Display for TypeType<'a, 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<S>> {
-        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<S> {
-        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<S> {
+    pub name: ArcStr,
+    pub description: Option<ArcStr>,
+    pub locations: Vec<DirectiveLocation>,
+    pub arguments: Vec<Argument<S>>,
+    pub is_repeatable: bool,
+}
+
+impl<S> DirectiveType<S> {
     pub fn new(
-        name: &str,
+        name: impl Into<ArcStr>,
         locations: &[DirectiveLocation],
-        arguments: &[Argument<'a, S>],
+        arguments: &[Argument<S>],
         is_repeatable: bool,
-    ) -> Self {
+    ) -> Self
+    where
+        S: Clone,
+    {
         Self {
             name: name.into(),
             description: None,
@@ -600,73 +579,89 @@ where
         }
     }
 
-    fn new_skip(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S>
+    fn new_skip(registry: &mut Registry<S>) -> Self
     where
         S: ScalarValue,
     {
         Self::new(
-            "skip",
+            arcstr::literal!("skip"),
             &[
                 DirectiveLocation::Field,
                 DirectiveLocation::FragmentSpread,
                 DirectiveLocation::InlineFragment,
             ],
-            &[registry.arg::<bool>("if", &())],
+            &[registry.arg::<bool>(arcstr::literal!("if"), &())],
             false,
         )
     }
 
-    fn new_include(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S>
+    fn new_include(registry: &mut Registry<S>) -> Self
     where
         S: ScalarValue,
     {
         Self::new(
-            "include",
+            arcstr::literal!("include"),
             &[
                 DirectiveLocation::Field,
                 DirectiveLocation::FragmentSpread,
                 DirectiveLocation::InlineFragment,
             ],
-            &[registry.arg::<bool>("if", &())],
+            &[registry.arg::<bool>(arcstr::literal!("if"), &())],
             false,
         )
     }
 
-    fn new_deprecated(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S>
+    fn new_deprecated(registry: &mut Registry<S>) -> Self
     where
         S: ScalarValue,
     {
         Self::new(
-            "deprecated",
+            arcstr::literal!("deprecated"),
             &[
                 DirectiveLocation::FieldDefinition,
                 DirectiveLocation::EnumValue,
             ],
-            &[registry.arg::<String>("reason", &())],
+            &[registry.arg::<String>(arcstr::literal!("reason"), &())],
             false,
         )
     }
 
-    fn new_specified_by(registry: &mut Registry<'a, S>) -> DirectiveType<'a, S>
+    fn new_specified_by(registry: &mut Registry<S>) -> Self
     where
         S: ScalarValue,
     {
         Self::new(
-            "specifiedBy",
+            arcstr::literal!("specifiedBy"),
             &[DirectiveLocation::Scalar],
-            &[registry.arg::<String>("url", &())],
+            &[registry.arg::<String>(arcstr::literal!("url"), &())],
             false,
         )
     }
 
-    pub fn description(mut self, description: &str) -> DirectiveType<'a, S> {
+    pub fn description(mut self, description: impl Into<ArcStr>) -> 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 +678,6 @@ impl fmt::Display for DirectiveLocation {
     }
 }
 
-impl<'a, S> fmt::Display for TypeType<'a, 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<S>(types: &mut [TypeType<S>]) {
     types.sort_by(|a, b| {
@@ -718,18 +703,18 @@ mod concrete_type_sort {
     /// Returns a [`TypeType`] sorting weight by its type.
     pub fn by_type<S>(t: &TypeType<S>) -> 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 +729,11 @@ 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,
         }
     }
 }
diff --git a/juniper/src/schema/schema.rs b/juniper/src/schema/schema.rs
index 9ec47e33f..3c344d172 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},
@@ -17,28 +19,25 @@ use crate::schema::{
     model::{DirectiveLocation, DirectiveType, RootNode, SchemaType, TypeType},
 };
 
-impl<'a, S, QueryT, MutationT, SubscriptionT> GraphQLType<S>
-    for RootNode<'a, QueryT, MutationT, SubscriptionT, S>
+impl<S, QueryT, MutationT, SubscriptionT> GraphQLType<S>
+    for RootNode<QueryT, MutationT, SubscriptionT, S>
 where
     S: ScalarValue,
     QueryT: GraphQLType<S>,
     MutationT: GraphQLType<S, Context = QueryT::Context>,
     SubscriptionT: GraphQLType<S, Context = QueryT::Context>,
 {
-    fn name(info: &Self::TypeInfo) -> Option<&str> {
+    fn name(info: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         QueryT::meta(info, registry)
     }
 }
 
-impl<'a, S, QueryT, MutationT, SubscriptionT> GraphQLValue<S>
-    for RootNode<'a, QueryT, MutationT, SubscriptionT, S>
+impl<S, QueryT, MutationT, SubscriptionT> GraphQLValue<S>
+    for RootNode<QueryT, MutationT, SubscriptionT, S>
 where
     S: ScalarValue,
     QueryT: GraphQLType<S>,
@@ -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<ArcStr> {
         QueryT::name(info)
     }
 
@@ -99,7 +98,7 @@ where
 }
 
 impl<'a, S, QueryT, MutationT, SubscriptionT> GraphQLValueAsync<S>
-    for RootNode<'a, QueryT, MutationT, SubscriptionT, S>
+    for RootNode<QueryT, MutationT, SubscriptionT, S>
 where
     QueryT: GraphQLTypeAsync<S>,
     QueryT::TypeInfo: Sync,
@@ -117,11 +116,12 @@ where
         arguments: &'b Arguments<S>,
         executor: &'b Executor<Self::Context, S>,
     ) -> crate::BoxFuture<'b, ExecutionResult<S>> {
-        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<S>,
     scalar = S,
     internal,
 )]
-impl<'a, S: ScalarValue + 'a> SchemaType<'a, S> {
-    fn description(&self) -> Option<&str> {
-        self.description.as_deref()
+impl<S: ScalarValue> SchemaType<S> {
+    fn description(&self) -> Option<&ArcStr> {
+        self.description.as_ref()
     }
 
     fn types(&self) -> Vec<TypeType<S>> {
@@ -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<S>,
     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,101 +218,130 @@ impl<'a, S: ScalarValue + 'a> TypeType<'a, S> {
         #[graphql(default = false)] include_deprecated: Option<bool>,
     ) -> Option<Vec<&Field<S>>> {
         match self {
-            TypeType::Concrete(&MetaType::Interface(InterfaceMeta { ref fields, .. }))
-            | TypeType::Concrete(&MetaType::Object(ObjectMeta { ref 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<S>> {
+    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<S>]> {
         match self {
-            TypeType::Concrete(&MetaType::InputObject(InputObjectMeta {
-                ref 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<Vec<TypeType<'s, S>>> {
+    fn interfaces<'s>(&self, context: &'s SchemaType<S>) -> Option<Vec<TypeType<'s, S>>> {
         match self {
-            TypeType::Concrete(
-                &MetaType::Object(ObjectMeta {
-                    ref interface_names,
-                    ..
+            Self::Concrete(t) => match t {
+                MetaType::Interface(InterfaceMeta {
+                    interface_names, ..
                 })
-                | &MetaType::Interface(InterfaceMeta {
-                    ref interface_names,
-                    ..
-                }),
-            ) => Some(
-                interface_names
-                    .iter()
-                    .filter_map(|n| context.type_by_name(n))
-                    .collect(),
-            ),
-            _ => None,
+                | MetaType::Object(ObjectMeta {
+                    interface_names, ..
+                }) => 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<Vec<TypeType<'s, S>>> {
+    fn possible_types<'s>(&self, context: &'s SchemaType<S>) -> Option<Vec<TypeType<'s, S>>> {
         match self {
-            TypeType::Concrete(&MetaType::Union(UnionMeta {
-                ref of_type_names, ..
-            })) => Some(
-                of_type_names
-                    .iter()
-                    .filter_map(|tn| context.type_by_name(tn))
-                    .collect(),
-            ),
-            TypeType::Concrete(&MetaType::Interface(InterfaceMeta {
-                name: ref 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::<Vec<_>>();
-                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(|| name.as_ref())
+                            } else {
+                                None
+                            }
+                        })
+                        .collect::<Vec<_>>();
+                    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,
         }
     }
 
@@ -319,34 +350,45 @@ impl<'a, S: ScalarValue + 'a> TypeType<'a, S> {
         #[graphql(default = false)] include_deprecated: Option<bool>,
     ) -> Option<Vec<&EnumValue>> {
         match self {
-            TypeType::Concrete(&MetaType::Enum(EnumMeta { ref 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<S>,
     scalar = S,
     internal,
 )]
-impl<'a, S: ScalarValue + 'a> Field<'a, S> {
-    fn name(&self) -> String {
-        self.name.clone().into()
+impl<S: ScalarValue> Field<S> {
+    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<S>> {
@@ -356,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<S>) -> TypeType<'s, S> {
         context.make_type(&self.field_type)
     }
 
@@ -364,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<S>,
     scalar = S,
     internal,
 )]
-impl<'a, S: ScalarValue + 'a> Argument<'a, S> {
-    fn name(&self) -> &str {
+impl<S: ScalarValue> Argument<S> {
+    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<S>) -> TypeType<'s, S> {
         context.make_type(&self.arg_type)
     }
 
@@ -396,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<S>,
     scalar = S,
     internal,
 )]
-impl<'a, S: ScalarValue + 'a> DirectiveType<'a, S> {
-    fn name(&self) -> &str {
+impl<S: ScalarValue> DirectiveType<S> {
+    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 0fac42caa..00a257b83 100644
--- a/juniper/src/schema/translate/graphql_parser.rs
+++ b/juniper/src/schema/translate/graphql_parser.rs
@@ -25,12 +25,12 @@ use crate::{
 
 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<S>> 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<S>) -> Document<'a, T> {
         GraphQLParserTranslator::translate_schema(input)
     }
 }
@@ -60,15 +60,12 @@ where
             .push(Definition::SchemaDefinition(SchemaDefinition {
                 position: Pos::default(),
                 directives: vec![],
-                query: Some(From::from(input.query_type_name.as_str())),
-                mutation: input
-                    .mutation_type_name
-                    .as_ref()
-                    .map(|s| From::from(s.as_str())),
+                query: Some(input.query_type_name.as_str().into()),
+                mutation: input.mutation_type_name.as_ref().map(|s| s.as_str().into()),
                 subscription: input
                     .subscription_type_name
                     .as_ref()
-                    .map(|s| From::from(s.as_str())),
+                    .map(|s| s.as_str().into()),
             }));
 
         doc
@@ -83,8 +80,8 @@ impl GraphQLParserTranslator {
     {
         ExternalInputValue {
             position: Pos::default(),
-            description: input.description.as_ref().map(From::from),
-            name: From::from(input.name.as_str()),
+            description: input.description.as_deref().map(Into::into),
+            name: input.name.as_str().into(),
             value_type: GraphQLParserTranslator::translate_type(&input.arg_type),
             default_value: input
                 .default_value
@@ -125,7 +122,7 @@ impl GraphQLParserTranslator {
                 let mut fields = BTreeMap::new();
                 x.iter().for_each(|(name_span, value_span)| {
                     fields.insert(
-                        From::from(name_span.item.as_str()),
+                        name_span.item.as_str().into(),
                         GraphQLParserTranslator::translate_value(&value_span.item),
                     );
                 });
@@ -139,16 +136,16 @@ impl GraphQLParserTranslator {
         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(x.as_ref().into()),
+            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()))))
+                ExternalType::NonNullType(Box::new(ExternalType::NamedType(x.as_ref().into())))
             }
-            Type::NonNullList(x, _) => ExternalType::NonNullType(Box::new(ExternalType::ListType(
-                Box::new(GraphQLParserTranslator::translate_type(x)),
-            ))),
         }
     }
 
@@ -160,13 +157,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
@@ -177,7 +174,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
@@ -188,7 +185,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
@@ -206,7 +203,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
@@ -219,7 +216,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
@@ -245,7 +242,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),
         }
     }
@@ -268,8 +265,8 @@ 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())),
+            name: input.name.as_str().into(),
+            description: input.description.as_deref().map(Into::into),
             directives: generate_directives(&input.deprecation_status),
             field_type: GraphQLParserTranslator::translate_type(&input.field_type),
             arguments,
@@ -288,7 +285,7 @@ where
             name: "deprecated".into(),
             arguments: reason
                 .as_ref()
-                .map(|rsn| vec![(From::from("reason"), ExternalValue::String(rsn.into()))])
+                .map(|rsn| vec![("reason".into(), ExternalValue::String(rsn.as_str().into()))])
                 .unwrap_or_default(),
         }),
     }
diff --git a/juniper/src/tests/subscriptions.rs b/juniper/src/tests/subscriptions.rs
index a4171651d..51a8114ad 100644
--- a/juniper/src/tests/subscriptions.rs
+++ b/juniper/src/tests/subscriptions.rs
@@ -30,8 +30,7 @@ impl MyQuery {
     }
 }
 
-type Schema =
-    RootNode<'static, MyQuery, EmptyMutation<MyContext>, MySubscription, DefaultScalarValue>;
+type Schema = RootNode<MyQuery, EmptyMutation<MyContext>, MySubscription, DefaultScalarValue>;
 
 fn run<O>(f: impl std::future::Future<Output = O>) -> 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<String>,
+    name: ArcStr,
+    attribute_names: Vec<ArcStr>,
 }
 
 pub struct Node {
@@ -24,18 +25,15 @@ impl<S> GraphQLType<S> for Node
 where
     S: ScalarValue,
 {
-    fn name(info: &Self::TypeInfo) -> Option<&str> {
-        Some(&info.name)
+    fn name(info: &Self::TypeInfo) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = info
             .attribute_names
             .iter()
-            .map(|name| registry.field::<String>(name, &()))
+            .map(|name| registry.field::<String>(name.clone(), &()))
             .collect::<Vec<_>>();
 
         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<ArcStr> {
         <Self as GraphQLType<S>>::name(info)
     }
 
diff --git a/juniper/src/types/async_await.rs b/juniper/src/types/async_await.rs
index d86ed01be..1fb94c9c5 100644
--- a/juniper/src/types/async_await.rs
+++ b/juniper/src/types/async_await.rs
@@ -307,7 +307,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 8392d24a0..005ca06db 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<ArcStr>;
 
     /// 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<String> }
 ///
 /// impl GraphQLType<DefaultScalarValue> for User {
-///    fn name(_: &()) -> Option<&'static str> {
-///        Some("User")
+///    fn name(_: &()) -> Option<ArcStr> {
+///        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::<Vec<&User>>("friends", &()),
+///            registry.field::<String>(arcstr::literal!("id"), &()),
+///            registry.field::<String>(arcstr::literal!("name"), &()),
+///            registry.field::<Vec<User>>(arcstr::literal!("friends"), &()),
 ///        ];
 ///        registry.build_object_type::<User>(&(), 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<ArcStr> {
 ///         <User as GraphQLType>::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<ArcStr>;
 
     /// 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<S>) -> MetaType<S>;
 }
 
 /// Resolver logic for queries'/mutations' selection set.
@@ -524,7 +521,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 108f0e021..c6bea24f6 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>,
     S: ScalarValue,
 {
-    fn name(_: &Self::TypeInfo) -> Option<&'static str> {
+    fn name(_: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         registry.build_nullable_type::<T>(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<ArcStr> {
         None
     }
 
@@ -105,14 +104,11 @@ where
     T: GraphQLType<S>,
     S: ScalarValue,
 {
-    fn name(_: &Self::TypeInfo) -> Option<&'static str> {
+    fn name(_: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         registry.build_list_type::<T>(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<ArcStr> {
         None
     }
 
@@ -225,14 +221,11 @@ where
     S: ScalarValue,
     T: GraphQLType<S>,
 {
-    fn name(_: &Self::TypeInfo) -> Option<&'static str> {
+    fn name(_: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         registry.build_list_type::<T>(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<ArcStr> {
         None
     }
 
@@ -292,14 +285,11 @@ where
     S: ScalarValue,
     T: GraphQLType<S>,
 {
-    fn name(_: &Self::TypeInfo) -> Option<&'static str> {
+    fn name(_: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         registry.build_list_type::<T>(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<ArcStr> {
         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<S>(input: S) -> Result<Self, NameParseError>
+    where
+        S: AsRef<str> + Into<ArcStr>,
+    {
+        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<ArcStr> for Name {
+    fn borrow(&self) -> &ArcStr {
+        &self.0
     }
 }
 
-impl Error for NameParseError {
-    fn description(&self) -> &str {
+impl Borrow<str> for Name {
+    fn borrow(&self) -> &str {
         &self.0
     }
 }
 
-impl FromStr for Name {
-    type Err = NameParseError;
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        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<String> 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<str> 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>,
     S: ScalarValue,
 {
-    fn name(_: &Self::TypeInfo) -> Option<&'static str> {
+    fn name(_: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         registry.build_nullable_type::<T>(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<ArcStr> {
         None
     }
 
diff --git a/juniper/src/types/pointers.rs b/juniper/src/types/pointers.rs
index 17e706799..386ae50d2 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::{
     ast::{FromInputValue, InputValue, Selection, ToInputValue},
     executor::{ExecutionResult, Executor, Registry},
@@ -17,14 +19,11 @@ where
     T: GraphQLType<S> + ?Sized,
     S: ScalarValue,
 {
-    fn name(info: &Self::TypeInfo) -> Option<&str> {
+    fn name(info: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         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<ArcStr> {
         (**self).type_name(info)
     }
 
@@ -115,14 +114,11 @@ where
     T: GraphQLType<S> + ?Sized,
     S: ScalarValue,
 {
-    fn name(info: &Self::TypeInfo) -> Option<&str> {
+    fn name(info: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         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<ArcStr> {
         (**self).type_name(info)
     }
 
@@ -211,14 +207,11 @@ where
     S: ScalarValue,
     T: GraphQLType<S> + ?Sized,
 {
-    fn name(info: &Self::TypeInfo) -> Option<&str> {
+    fn name(info: &Self::TypeInfo) -> Option<ArcStr> {
         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<S>) -> MetaType<S> {
         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<ArcStr> {
         (**self).type_name(info)
     }
 
diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs
index c904fcabf..87423749a 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<S: ScalarValue>(v: &ArcStr) -> Value<S> {
+        Value::scalar(v.to_string())
+    }
+
+    pub(super) fn from_input<S: ScalarValue>(v: &InputValue<S>) -> Result<ArcStr, String> {
+        v.as_string_value()
+            .map(Into::into)
+            .ok_or_else(|| format!("Expected `String`, found: {v}"))
+    }
+}
+
 impl<S> reflect::WrappedType<S> for str {
     const VALUE: reflect::WrappedValue = 1;
 }
@@ -202,14 +223,11 @@ impl<S> GraphQLType<S> for str
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("String")
+    fn name(_: &()) -> Option<ArcStr> {
+        Some(arcstr::literal!("String"))
     }
 
-    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-    where
-        S: 'r,
-    {
+    fn meta(_: &(), registry: &mut Registry<S>) -> MetaType<S> {
         registry.build_scalar_type::<String>(&()).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<ArcStr> {
         <Self as GraphQLType<S>>::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<S, T> GraphQLType<S> for EmptyMutation<T>
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("_EmptyMutation")
+    fn name(_: &()) -> Option<ArcStr> {
+        Some(arcstr::literal!("_EmptyMutation"))
     }
 
-    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-    where
-        S: 'r,
-    {
+    fn meta(_: &(), registry: &mut Registry<S>) -> MetaType<S> {
         registry.build_object_type::<Self>(&(), &[]).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<ArcStr> {
         <Self as GraphQLType<S>>::name(info)
     }
 }
@@ -420,14 +438,11 @@ impl<S, T> GraphQLType<S> for EmptySubscription<T>
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("_EmptySubscription")
+    fn name(_: &()) -> Option<ArcStr> {
+        Some(arcstr::literal!("_EmptySubscription"))
     }
 
-    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-    where
-        S: 'r,
-    {
+    fn meta(_: &(), registry: &mut Registry<S>) -> MetaType<S> {
         registry.build_object_type::<Self>(&(), &[]).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<ArcStr> {
         <Self as GraphQLType<S>>::name(info)
     }
 }
diff --git a/juniper/src/types/subscriptions.rs b/juniper/src/types/subscriptions.rs
index 3e8211b8a..93a587a0c 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");
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<S>(
     schema: &SchemaType<S>,
     arg_type: &TypeType<S>,
@@ -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::<HashSet<_>>();
 
                         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::<Vec<_>>()
                                 .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..7af7d3514 100644
--- a/juniper/src/validation/context.rs
+++ b/juniper/src/validation/context.rs
@@ -3,11 +3,11 @@ use std::{
     fmt::{self, Debug},
 };
 
-use crate::ast::{Definition, Document, Type};
-
-use crate::schema::{meta::MetaType, model::SchemaType};
-
-use crate::parser::SourcePosition;
+use crate::{
+    ast::{Definition, Document, Type},
+    parser::SourcePosition,
+    schema::{meta::MetaType, model::SchemaType},
+};
 
 /// Query validation error
 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
@@ -18,13 +18,13 @@ pub struct RuleError {
 
 #[doc(hidden)]
 pub struct ValidatorContext<'a, S: Debug + 'a> {
-    pub schema: &'a SchemaType<'a, S>,
+    pub schema: &'a SchemaType<S>,
     errors: Vec<RuleError>,
-    type_stack: Vec<Option<&'a MetaType<'a, S>>>,
+    type_stack: Vec<Option<&'a MetaType<S>>>,
     type_literal_stack: Vec<Option<Type<'a>>>,
-    input_type_stack: Vec<Option<&'a MetaType<'a, S>>>,
+    input_type_stack: Vec<Option<&'a MetaType<S>>>,
     input_type_literal_stack: Vec<Option<Type<'a>>>,
-    parent_type_stack: Vec<Option<&'a MetaType<'a, S>>>,
+    parent_type_stack: Vec<Option<&'a MetaType<S>>>,
     fragment_names: HashSet<&'a str>,
 }
 
@@ -120,6 +120,7 @@ impl<'a, S: Debug> ValidatorContext<'a, S> {
             self.type_stack.push(None);
         }
 
+        // TODO: no cloning
         self.type_literal_stack.push(t.cloned());
 
         let res = f(self);
@@ -155,6 +156,7 @@ impl<'a, S: Debug> ValidatorContext<'a, S> {
             self.input_type_stack.push(None);
         }
 
+        // TODO: no cloning
         self.input_type_literal_stack.push(t.cloned());
 
         let res = f(self);
@@ -166,7 +168,7 @@ 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<S>> {
         *self.type_stack.last().unwrap_or(&None)
     }
 
@@ -179,7 +181,7 @@ impl<'a, S: Debug> ValidatorContext<'a, S> {
     }
 
     #[doc(hidden)]
-    pub fn parent_type(&self) -> Option<&'a MetaType<'a, S>> {
+    pub fn parent_type(&self) -> Option<&'a MetaType<S>> {
         *self.parent_type_stack.last().unwrap_or(&None)
     }
 
diff --git a/juniper/src/validation/rules/arguments_of_correct_type.rs b/juniper/src/validation/rules/arguments_of_correct_type.rs
index 4524cf8d6..951f5d44f 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<Argument<'a, S>>>,
+    current_args: Option<&'a Vec<Argument<S>>>,
 }
 
 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 1e3f7e028..bc7acc689 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::{
     ast::Field,
     parser::Spanning,
@@ -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("<unknown>");
+                let type_name = parent_type
+                    .name()
+                    .map(ArcStr::as_str)
+                    .unwrap_or("<unknown>");
 
                 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 c5e9b804f..cf80178b0 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("<unknown>");
+                    let type_name = current_type
+                        .name()
+                        .map(ArcStr::as_str)
+                        .unwrap_or("<unknown>");
                     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("<unknown>"))
+                    .map(|t| t.name().map(ArcStr::as_str).unwrap_or("<unknown>"))
                     .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 c8e11820f..171898e3d 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<Argument<'a, S>>)>,
+    current_args: Option<(ArgumentPosition<'a>, &'a Vec<Argument<S>>)>,
 }
 
 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 a41610d3f..1db736781 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<Field<'a, S>>,
-    Option<&'a FieldType<'a, S>>,
+    Option<&'a FieldType<S>>,
 );
 
 type AstAndDefCollection<'a, S> = OrderedMap<&'a str, Vec<AstAndDef<'a, S>>>;
@@ -444,9 +446,9 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> {
         if let (Some(s1), Some(s2)) = (&ast1.item.selection_set, &ast2.item.selection_set) {
             let conflicts = self.find_conflicts_between_sub_selection_sets(
                 mutually_exclusive,
-                t1.map(Type::innermost_name),
+                t1.map(|t| t.innermost_name().as_ref()),
                 s1,
-                t2.map(Type::innermost_name),
+                t2.map(|t| t.innermost_name().as_ref()),
                 s2,
                 ctx,
             );
@@ -554,20 +556,20 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> {
         ))
     }
 
-    fn is_type_conflict(ctx: &ValidatorContext<'a, S>, t1: &Type, t2: &Type) -> bool {
+    fn is_type_conflict(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)) => {
+            (Type::Named(n1), Type::Named(n2))
+            | (Type::NonNullNamed(n1), Type::NonNullNamed(n2)) => {
                 let ct1 = ctx.schema.concrete_type_by_name(n1);
                 let ct2 = ctx.schema.concrete_type_by_name(n2);
 
@@ -674,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,
                     ));
@@ -761,6 +763,8 @@ fn format_reason(reason: &ConflictReasonMessage) -> String {
 
 #[cfg(test)]
 mod tests {
+    use arcstr::ArcStr;
+
     use super::{error_message, factory, ConflictReason, ConflictReasonMessage::*};
 
     use crate::{
@@ -1400,18 +1404,15 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("SomeBox")
+        fn name(_: &()) -> Option<ArcStr> {
+            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<S>) -> MetaType<S> {
             let fields = &[
-                registry.field::<Option<SomeBox>>("deepBox", i),
-                registry.field::<Option<String>>("unrelatedField", i),
-                registry.field::<Option<String>>("otherField", i),
+                registry.field::<Option<SomeBox>>(arcstr::literal!("deepBox"), i),
+                registry.field::<Option<String>>(arcstr::literal!("unrelatedField"), i),
+                registry.field::<Option<String>>(arcstr::literal!("otherField"), i),
             ];
 
             registry.build_interface_type::<Self>(i, fields).into_meta()
@@ -1425,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1434,21 +1435,19 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("StringBox")
+        fn name(_: &()) -> Option<ArcStr> {
+            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<S>) -> MetaType<S> {
             let fields = &[
-                registry.field::<Option<String>>("scalar", i),
-                registry.field::<Option<StringBox>>("deepBox", i),
-                registry.field::<Option<String>>("unrelatedField", i),
-                registry.field::<Option<Vec<Option<StringBox>>>>("listStringBox", i),
-                registry.field::<Option<StringBox>>("stringBox", i),
-                registry.field::<Option<IntBox>>("intBox", i),
+                registry.field::<Option<String>>(arcstr::literal!("scalar"), i),
+                registry.field::<Option<StringBox>>(arcstr::literal!("deepBox"), i),
+                registry.field::<Option<String>>(arcstr::literal!("unrelatedField"), i),
+                registry
+                    .field::<Option<Vec<Option<StringBox>>>>(arcstr::literal!("listStringBox"), i),
+                registry.field::<Option<StringBox>>(arcstr::literal!("stringBox"), i),
+                registry.field::<Option<IntBox>>(arcstr::literal!("intBox"), i),
             ];
 
             registry
@@ -1465,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1474,21 +1473,19 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("IntBox")
+        fn name(_: &()) -> Option<ArcStr> {
+            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<S>) -> MetaType<S> {
             let fields = &[
-                registry.field::<Option<i32>>("scalar", i),
-                registry.field::<Option<IntBox>>("deepBox", i),
-                registry.field::<Option<String>>("unrelatedField", i),
-                registry.field::<Option<Vec<Option<StringBox>>>>("listStringBox", i),
-                registry.field::<Option<StringBox>>("stringBox", i),
-                registry.field::<Option<IntBox>>("intBox", i),
+                registry.field::<Option<i32>>(arcstr::literal!("scalar"), i),
+                registry.field::<Option<IntBox>>(arcstr::literal!("deepBox"), i),
+                registry.field::<Option<String>>(arcstr::literal!("unrelatedField"), i),
+                registry
+                    .field::<Option<Vec<Option<StringBox>>>>(arcstr::literal!("listStringBox"), i),
+                registry.field::<Option<StringBox>>(arcstr::literal!("stringBox"), i),
+                registry.field::<Option<IntBox>>(arcstr::literal!("intBox"), i),
             ];
 
             registry
@@ -1505,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1514,15 +1511,12 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("NonNullStringBox1")
+        fn name(_: &()) -> Option<ArcStr> {
+            Some(arcstr::literal!("NonNullStringBox1"))
         }
 
-        fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-        where
-            S: 'r,
-        {
-            let fields = &[registry.field::<String>("scalar", i)];
+        fn meta(i: &(), registry: &mut Registry<S>) -> MetaType<S> {
+            let fields = &[registry.field::<String>(arcstr::literal!("scalar"), i)];
 
             registry.build_interface_type::<Self>(i, fields).into_meta()
         }
@@ -1535,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1544,18 +1538,15 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("NonNullStringBox1Impl")
+        fn name(_: &()) -> Option<ArcStr> {
+            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<S>) -> MetaType<S> {
             let fields = &[
-                registry.field::<String>("scalar", i),
-                registry.field::<Option<SomeBox>>("deepBox", i),
-                registry.field::<Option<String>>("unrelatedField", i),
+                registry.field::<String>(arcstr::literal!("scalar"), i),
+                registry.field::<Option<SomeBox>>(arcstr::literal!("deepBox"), i),
+                registry.field::<Option<String>>(arcstr::literal!("unrelatedField"), i),
             ];
 
             registry
@@ -1575,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1584,15 +1575,12 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("NonNullStringBox2")
+        fn name(_: &()) -> Option<ArcStr> {
+            Some(arcstr::literal!("NonNullStringBox2"))
         }
 
-        fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-        where
-            S: 'r,
-        {
-            let fields = &[registry.field::<String>("scalar", i)];
+        fn meta(i: &(), registry: &mut Registry<S>) -> MetaType<S> {
+            let fields = &[registry.field::<String>(arcstr::literal!("scalar"), i)];
 
             registry.build_interface_type::<Self>(i, fields).into_meta()
         }
@@ -1605,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1614,18 +1602,15 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("NonNullStringBox2Impl")
+        fn name(_: &()) -> Option<ArcStr> {
+            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<S>) -> MetaType<S> {
             let fields = &[
-                registry.field::<String>("scalar", i),
-                registry.field::<Option<SomeBox>>("deepBox", i),
-                registry.field::<Option<String>>("unrelatedField", i),
+                registry.field::<String>(arcstr::literal!("scalar"), i),
+                registry.field::<Option<SomeBox>>(arcstr::literal!("deepBox"), i),
+                registry.field::<Option<String>>(arcstr::literal!("unrelatedField"), i),
             ];
 
             registry
@@ -1645,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1654,17 +1639,14 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("Node")
+        fn name(_: &()) -> Option<ArcStr> {
+            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<S>) -> MetaType<S> {
             let fields = &[
-                registry.field::<Option<ID>>("id", i),
-                registry.field::<Option<String>>("name", i),
+                registry.field::<Option<ID>>(arcstr::literal!("id"), i),
+                registry.field::<Option<String>>(arcstr::literal!("name"), i),
             ];
 
             registry.build_object_type::<Self>(i, fields).into_meta()
@@ -1678,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1687,15 +1669,12 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("Edge")
+        fn name(_: &()) -> Option<ArcStr> {
+            Some(arcstr::literal!("Edge"))
         }
 
-        fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-        where
-            S: 'r,
-        {
-            let fields = &[registry.field::<Option<Node>>("node", i)];
+        fn meta(i: &(), registry: &mut Registry<S>) -> MetaType<S> {
+            let fields = &[registry.field::<Option<Node>>(arcstr::literal!("node"), i)];
 
             registry.build_object_type::<Self>(i, fields).into_meta()
         }
@@ -1708,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1717,15 +1696,13 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("Connection")
+        fn name(_: &()) -> Option<ArcStr> {
+            Some(arcstr::literal!("Connection"))
         }
 
-        fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-        where
-            S: 'r,
-        {
-            let fields = &[registry.field::<Option<Vec<Option<Edge>>>>("edges", i)];
+        fn meta(i: &(), registry: &mut Registry<S>) -> MetaType<S> {
+            let fields =
+                &[registry.field::<Option<Vec<Option<Edge>>>>(arcstr::literal!("edges"), i)];
 
             registry.build_object_type::<Self>(i, fields).into_meta()
         }
@@ -1738,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
@@ -1747,22 +1724,19 @@ mod tests {
     where
         S: ScalarValue,
     {
-        fn name(_: &()) -> Option<&'static str> {
-            Some("QueryRoot")
+        fn name(_: &()) -> Option<ArcStr> {
+            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<S>) -> MetaType<S> {
             registry.get_type::<IntBox>(i);
             registry.get_type::<StringBox>(i);
             registry.get_type::<NonNullStringBox1Impl>(i);
             registry.get_type::<NonNullStringBox2Impl>(i);
 
             let fields = &[
-                registry.field::<Option<SomeBox>>("someBox", i),
-                registry.field::<Option<Connection>>("connection", i),
+                registry.field::<Option<SomeBox>>(arcstr::literal!("someBox"), i),
+                registry.field::<Option<Connection>>(arcstr::literal!("connection"), i),
             ];
             registry.build_object_type::<Self>(i, fields).into_meta()
         }
@@ -1775,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<ArcStr> {
             <Self as GraphQLType>::name(info)
         }
     }
diff --git a/juniper/src/validation/rules/possible_fragment_spreads.rs b/juniper/src/validation/rules/possible_fragment_spreads.rs
index 856b33ec0..fd29f2041 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<S>>,
 }
 
 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("<unknown>"),
-                        frag_type.name().unwrap_or("<unknown>"),
+                        parent_type
+                            .name()
+                            .map(ArcStr::as_str)
+                            .unwrap_or("<unknown>"),
+                        frag_type.name().map(ArcStr::as_str).unwrap_or("<unknown>"),
                     ),
                     &[frag.span.start],
                 );
@@ -106,8 +110,11 @@ where
                 ctx.report_error(
                     &error_message(
                         Some(spread.item.name.item),
-                        parent_type.name().unwrap_or("<unknown>"),
-                        frag_type.name().unwrap_or("<unknown>"),
+                        parent_type
+                            .name()
+                            .map(ArcStr::as_str)
+                            .unwrap_or("<unknown>"),
+                        frag_type.name().map(ArcStr::as_str).unwrap_or("<unknown>"),
                     ),
                     &[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 1ec9b5665..fcd3a31ae 100644
--- a/juniper/src/validation/rules/variables_in_allowed_position.rs
+++ b/juniper/src/validation/rules/variables_in_allowed_position.rs
@@ -1,11 +1,10 @@
 use std::{
-    borrow::Cow,
     collections::{HashMap, HashSet},
     fmt,
 };
 
 use crate::{
-    ast::{Document, Fragment, FragmentSpread, Operation, Type, VariableDefinition},
+    ast::{Document, Fragment, FragmentSpread, Operation, Type, TypeName, VariableDefinition},
     parser::Spanning,
     validation::{ValidatorContext, Visitor},
     value::ScalarValue,
@@ -29,7 +28,7 @@ pub fn factory<'a, S: fmt::Debug>() -> VariableInAllowedPosition<'a, S> {
 
 pub struct VariableInAllowedPosition<'a, S: fmt::Debug + 'a> {
     spreads: HashMap<Scope<'a>, HashSet<&'a str>>,
-    variable_usages: HashMap<Scope<'a>, Vec<(SpannedInput<'a, String>, Type<'a>)>>,
+    variable_usages: HashMap<Scope<'a>, Vec<(SpannedInput<'a, String>, &'a Type<'a>)>>,
     #[allow(clippy::type_complexity)]
     variable_defs: HashMap<Scope<'a>, Vec<&'a (Spanning<&'a str>, VariableDefinition<'a, S>)>>,
     current_scope: Option<Scope<'a>>,
@@ -88,8 +87,10 @@ 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(TypeName::Borrowed(inner))
+                        }
+                        (_, ty) => ty.clone(),
                     };
 
                     if !ctx.schema.is_subtype(&expected_type, var_type) {
@@ -169,7 +170,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 1dd28ac66..2e8fc7396 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::{
     ast::{Document, FromInputValue, InputValue},
     executor::Registry,
@@ -76,17 +78,14 @@ impl<S> GraphQLType<S> for Being
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Being")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[registry
-            .field::<Option<String>>("name", i)
-            .argument(registry.arg::<Option<bool>>("surname", i))];
+            .field::<Option<String>>(arcstr::literal!("name"), i)
+            .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i))];
 
         registry.build_interface_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -108,17 +107,14 @@ impl<S> GraphQLType<S> for Pet
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Pet")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[registry
-            .field::<Option<String>>("name", i)
-            .argument(registry.arg::<Option<bool>>("surname", i))];
+            .field::<Option<String>>(arcstr::literal!("name"), i)
+            .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i))];
 
         registry.build_interface_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -140,17 +136,14 @@ impl<S> GraphQLType<S> for Canine
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Canine")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[registry
-            .field::<Option<String>>("name", i)
-            .argument(registry.arg::<Option<bool>>("surname", i))];
+            .field::<Option<String>>(arcstr::literal!("name"), i)
+            .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i))];
 
         registry.build_interface_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -172,17 +165,14 @@ impl<S> GraphQLType<S> for Unpopulated
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Unpopulated")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[registry
-            .field::<Option<String>>("name", i)
-            .argument(registry.arg::<Option<bool>>("surname", i))];
+            .field::<Option<String>>(arcstr::literal!("name"), i)
+            .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i))];
 
         registry
             .build_interface_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -207,14 +197,11 @@ impl<S> GraphQLType<S> for DogCommand
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("DogCommand")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         registry
             .build_enum_type::<Self>(
                 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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -260,31 +247,28 @@ impl<S> GraphQLType<S> for Dog
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Dog")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[
             registry
-                .field::<Option<String>>("name", i)
-                .argument(registry.arg::<Option<bool>>("surname", i)),
-            registry.field::<Option<String>>("nickname", i),
-            registry.field::<Option<i32>>("barkVolume", i),
-            registry.field::<Option<bool>>("barks", i),
+                .field::<Option<String>>(arcstr::literal!("name"), i)
+                .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i)),
+            registry.field::<Option<String>>(arcstr::literal!("nickname"), i),
+            registry.field::<Option<i32>>(arcstr::literal!("barkVolume"), i),
+            registry.field::<Option<bool>>(arcstr::literal!("barks"), i),
             registry
-                .field::<Option<bool>>("doesKnowCommand", i)
-                .argument(registry.arg::<Option<DogCommand>>("dogCommand", i)),
+                .field::<Option<bool>>(arcstr::literal!("doesKnowCommand"), i)
+                .argument(registry.arg::<Option<DogCommand>>(arcstr::literal!("dogCommand"), i)),
             registry
-                .field::<Option<bool>>("isHousetrained", i)
-                .argument(registry.arg_with_default("atOtherHomes", &true, i)),
+                .field::<Option<bool>>(arcstr::literal!("isHousetrained"), i)
+                .argument(registry.arg_with_default(arcstr::literal!("atOtherHomes"), &true, i)),
             registry
-                .field::<Option<bool>>("isAtLocation", i)
-                .argument(registry.arg::<Option<i32>>("x", i))
-                .argument(registry.arg::<Option<i32>>("y", i)),
+                .field::<Option<bool>>(arcstr::literal!("isAtLocation"), i)
+                .argument(registry.arg::<Option<i32>>(arcstr::literal!("x"), i))
+                .argument(registry.arg::<Option<i32>>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -314,14 +298,11 @@ impl<S> GraphQLType<S> for FurColor
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("FurColor")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         registry
             .build_enum_type::<Self>(
                 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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -369,22 +350,19 @@ impl<S> GraphQLType<S> for Cat
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Cat")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[
             registry
-                .field::<Option<String>>("name", i)
-                .argument(registry.arg::<Option<bool>>("surname", i)),
-            registry.field::<Option<String>>("nickname", i),
-            registry.field::<Option<bool>>("meows", i),
-            registry.field::<Option<i32>>("meowVolume", i),
-            registry.field::<Option<FurColor>>("furColor", i),
+                .field::<Option<String>>(arcstr::literal!("name"), i)
+                .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i)),
+            registry.field::<Option<String>>(arcstr::literal!("nickname"), i),
+            registry.field::<Option<bool>>(arcstr::literal!("meows"), i),
+            registry.field::<Option<i32>>(arcstr::literal!("meowVolume"), i),
+            registry.field::<Option<FurColor>>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -410,14 +388,11 @@ impl<S> GraphQLType<S> for CatOrDog
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("CatOrDog")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let types = &[registry.get_type::<Cat>(i), registry.get_type::<Dog>(i)];
 
         registry.build_union_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -440,15 +415,12 @@ impl<S> GraphQLType<S> for Intelligent
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Intelligent")
+    fn name(_: &()) -> Option<ArcStr> {
+        Some(arcstr::literal!("Intelligent"))
     }
 
-    fn meta<'r>(i: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-    where
-        S: 'r,
-    {
-        let fields = &[registry.field::<Option<i32>>("iq", i)];
+    fn meta(i: &(), registry: &mut Registry<S>) -> MetaType<S> {
+        let fields = &[registry.field::<Option<i32>>(arcstr::literal!("iq"), i)];
 
         registry.build_interface_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -470,21 +442,18 @@ impl<S> GraphQLType<S> for Human
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Human")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[
             registry
-                .field::<Option<String>>("name", i)
-                .argument(registry.arg::<Option<bool>>("surname", i)),
-            registry.field::<Option<Vec<Option<Pet>>>>("pets", i),
-            registry.field::<Option<Vec<Human>>>("relatives", i),
-            registry.field::<Option<i32>>("iq", i),
+                .field::<Option<String>>(arcstr::literal!("name"), i)
+                .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i)),
+            registry.field::<Option<Vec<Option<Pet>>>>(arcstr::literal!("pets"), i),
+            registry.field::<Option<Vec<Human>>>(arcstr::literal!("relatives"), i),
+            registry.field::<Option<i32>>(arcstr::literal!("iq"), i),
         ];
         registry
             .build_object_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -512,20 +481,17 @@ impl<S> GraphQLType<S> for Alien
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("Alien")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[
             registry
-                .field::<Option<String>>("name", i)
-                .argument(registry.arg::<Option<bool>>("surname", i)),
-            registry.field::<Option<i32>>("iq", i),
-            registry.field::<Option<i32>>("numEyes", i),
+                .field::<Option<String>>(arcstr::literal!("name"), i)
+                .argument(registry.arg::<Option<bool>>(arcstr::literal!("surname"), i)),
+            registry.field::<Option<i32>>(arcstr::literal!("iq"), i),
+            registry.field::<Option<i32>>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -554,14 +520,11 @@ impl<S> GraphQLType<S> for DogOrHuman
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("DogOrHuman")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let types = &[registry.get_type::<Dog>(i), registry.get_type::<Human>(i)];
 
         registry.build_union_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -584,14 +547,11 @@ impl<S> GraphQLType<S> for HumanOrAlien
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("HumanOrAlien")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let types = &[registry.get_type::<Human>(i), registry.get_type::<Alien>(i)];
 
         registry.build_union_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -614,20 +574,17 @@ impl<S> GraphQLType<S> for ComplexInput
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("ComplexInput")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[
-            registry.arg::<bool>("requiredField", i),
-            registry.arg::<Option<i32>>("intField", i),
-            registry.arg::<Option<String>>("stringField", i),
-            registry.arg::<Option<bool>>("booleanField", i),
-            registry.arg::<Option<Vec<Option<String>>>>("stringListField", i),
+            registry.arg::<bool>(arcstr::literal!("requiredField"), i),
+            registry.arg::<Option<i32>>(arcstr::literal!("intField"), i),
+            registry.arg::<Option<String>>(arcstr::literal!("stringField"), i),
+            registry.arg::<Option<bool>>(arcstr::literal!("booleanField"), i),
+            registry.arg::<Option<Vec<Option<String>>>>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -691,59 +648,59 @@ impl<S> GraphQLType<S> for ComplicatedArgs
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("ComplicatedArgs")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[
             registry
-                .field::<Option<String>>("intArgField", i)
-                .argument(registry.arg::<Option<i32>>("intArg", i)),
+                .field::<Option<String>>(arcstr::literal!("intArgField"), i)
+                .argument(registry.arg::<Option<i32>>(arcstr::literal!("intArg"), i)),
             registry
-                .field::<Option<String>>("nonNullIntArgField", i)
-                .argument(registry.arg::<i32>("nonNullIntArg", i)),
+                .field::<Option<String>>(arcstr::literal!("nonNullIntArgField"), i)
+                .argument(registry.arg::<i32>(arcstr::literal!("nonNullIntArg"), i)),
             registry
-                .field::<Option<String>>("stringArgField", i)
-                .argument(registry.arg::<Option<String>>("stringArg", i)),
+                .field::<Option<String>>(arcstr::literal!("stringArgField"), i)
+                .argument(registry.arg::<Option<String>>(arcstr::literal!("stringArg"), i)),
             registry
-                .field::<Option<String>>("booleanArgField", i)
-                .argument(registry.arg::<Option<bool>>("booleanArg", i)),
+                .field::<Option<String>>(arcstr::literal!("booleanArgField"), i)
+                .argument(registry.arg::<Option<bool>>(arcstr::literal!("booleanArg"), i)),
             registry
-                .field::<Option<String>>("enumArgField", i)
-                .argument(registry.arg::<Option<FurColor>>("enumArg", i)),
+                .field::<Option<String>>(arcstr::literal!("enumArgField"), i)
+                .argument(registry.arg::<Option<FurColor>>(arcstr::literal!("enumArg"), i)),
             registry
-                .field::<Option<String>>("floatArgField", i)
-                .argument(registry.arg::<Option<f64>>("floatArg", i)),
+                .field::<Option<String>>(arcstr::literal!("floatArgField"), i)
+                .argument(registry.arg::<Option<f64>>(arcstr::literal!("floatArg"), i)),
             registry
-                .field::<Option<String>>("idArgField", i)
-                .argument(registry.arg::<Option<ID>>("idArg", i)),
+                .field::<Option<String>>(arcstr::literal!("idArgField"), i)
+                .argument(registry.arg::<Option<ID>>(arcstr::literal!("idArg"), i)),
             registry
-                .field::<Option<String>>("stringListArgField", i)
-                .argument(registry.arg::<Option<Vec<Option<String>>>>("stringListArg", i)),
+                .field::<Option<String>>(arcstr::literal!("stringListArgField"), i)
+                .argument(
+                    registry
+                        .arg::<Option<Vec<Option<String>>>>(arcstr::literal!("stringListArg"), i),
+                ),
             registry
-                .field::<Option<String>>("nonNullStringListArgField", i)
-                .argument(registry.arg::<Vec<String>>("nonNullStringListArg", i)),
+                .field::<Option<String>>(arcstr::literal!("nonNullStringListArgField"), i)
+                .argument(registry.arg::<Vec<String>>(arcstr::literal!("nonNullStringListArg"), i)),
             registry
-                .field::<Option<String>>("complexArgField", i)
-                .argument(registry.arg::<Option<ComplexInput>>("complexArg", i)),
+                .field::<Option<String>>(arcstr::literal!("complexArgField"), i)
+                .argument(registry.arg::<Option<ComplexInput>>(arcstr::literal!("complexArg"), i)),
             registry
-                .field::<Option<String>>("multipleReqs", i)
-                .argument(registry.arg::<i32>("req1", i))
-                .argument(registry.arg::<i32>("req2", i)),
+                .field::<Option<String>>(arcstr::literal!("multipleReqs"), i)
+                .argument(registry.arg::<i32>(arcstr::literal!("req1"), i))
+                .argument(registry.arg::<i32>(arcstr::literal!("req2"), i)),
             registry
-                .field::<Option<String>>("multipleOpts", i)
-                .argument(registry.arg_with_default("opt1", &0i32, i))
-                .argument(registry.arg_with_default("opt2", &0i32, i)),
+                .field::<Option<String>>(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::<Option<String>>("multipleOptAndReq", i)
-                .argument(registry.arg::<i32>("req1", i))
-                .argument(registry.arg::<i32>("req2", i))
-                .argument(registry.arg_with_default("opt1", &0i32, i))
-                .argument(registry.arg_with_default("opt2", &0i32, i)),
+                .field::<Option<String>>(arcstr::literal!("multipleOptAndReq"), i)
+                .argument(registry.arg::<i32>(arcstr::literal!("req1"), i))
+                .argument(registry.arg::<i32>(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::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -766,26 +723,23 @@ impl<S> GraphQLType<S> for QueryRoot
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&'static str> {
-        Some("QueryRoot")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = &[
             registry
-                .field::<Option<Human>>("human", i)
-                .argument(registry.arg::<Option<ID>>("id", i)),
-            registry.field::<Option<Alien>>("alien", i),
-            registry.field::<Option<Dog>>("dog", i),
-            registry.field::<Option<Cat>>("cat", i),
-            registry.field::<Option<Pet>>("pet", i),
-            registry.field::<Option<CatOrDog>>("catOrDog", i),
-            registry.field::<Option<DogOrHuman>>("dorOrHuman", i),
-            registry.field::<Option<HumanOrAlien>>("humanOrAlien", i),
-            registry.field::<Option<ComplicatedArgs>>("complicatedArgs", i),
+                .field::<Option<Human>>(arcstr::literal!("human"), i)
+                .argument(registry.arg::<Option<ID>>(arcstr::literal!("id"), i)),
+            registry.field::<Option<Alien>>(arcstr::literal!("alien"), i),
+            registry.field::<Option<Dog>>(arcstr::literal!("dog"), i),
+            registry.field::<Option<Cat>>(arcstr::literal!("cat"), i),
+            registry.field::<Option<Pet>>(arcstr::literal!("pet"), i),
+            registry.field::<Option<CatOrDog>>(arcstr::literal!("catOrDog"), i),
+            registry.field::<Option<DogOrHuman>>(arcstr::literal!("dorOrHuman"), i),
+            registry.field::<Option<HumanOrAlien>>(arcstr::literal!("humanOrAlien"), i),
+            registry.field::<Option<ComplicatedArgs>>(arcstr::literal!("complicatedArgs"), i),
         ];
 
         registry.build_object_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -808,26 +762,23 @@ impl<S> GraphQLType<S> for MutationRoot
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&str> {
-        Some("MutationRoot")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let _ = registry.get_type::<Unpopulated>(i);
 
-        let fields = [registry.field::<i32>("testInput", i).argument(
-            registry.arg_with_default::<TestInput>(
-                "input",
+        let fields = [registry
+            .field::<i32>(arcstr::literal!("testInput"), i)
+            .argument(registry.arg_with_default::<TestInput>(
+                arcstr::literal!("input"),
                 &TestInput {
                     id: 423,
                     name: String::from("foo"),
                 },
                 i,
-            ),
-        )];
+            ))];
 
         registry.build_object_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
@@ -849,14 +800,11 @@ impl<S> GraphQLType<S> for SubscriptionRoot
 where
     S: ScalarValue,
 {
-    fn name(_: &()) -> Option<&str> {
-        Some("SubscriptionRoot")
+    fn name(_: &()) -> Option<ArcStr> {
+        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<S>) -> MetaType<S> {
         let fields = [];
 
         registry.build_object_type::<Self>(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<ArcStr> {
         <Self as GraphQLType>::name(info)
     }
 }
diff --git a/juniper/src/validation/visitor.rs b/juniper/src/validation/visitor.rs
index 17d20ad12..bb32991d3 100644
--- a/juniper/src/validation/visitor.rs
+++ b/juniper/src/validation/visitor.rs
@@ -1,5 +1,3 @@
-use std::borrow::Cow;
-
 use crate::{
     ast::{
         Arguments, Definition, Directive, Document, Field, Fragment, FragmentSpread,
@@ -39,7 +37,7 @@ where
                         ..
                     },
                 ..
-            }) => Some(Type::NonNullNamed(Cow::Borrowed(name))),
+            }) => Some(Type::NonNullNamed(name.into())),
             Definition::Operation(Spanning {
                 item:
                     Operation {
@@ -47,9 +45,9 @@ where
                         ..
                     },
                 ..
-            }) => Some(Type::NonNullNamed(Cow::Borrowed(
-                ctx.schema.concrete_query_type().name().unwrap(),
-            ))),
+            }) => Some(Type::NonNullNamed(
+                ctx.schema.concrete_query_type().name().unwrap().into(),
+            )),
             Definition::Operation(Spanning {
                 item:
                     Operation {
@@ -60,7 +58,7 @@ where
             }) => ctx
                 .schema
                 .concrete_mutation_type()
-                .map(|t| Type::NonNullNamed(Cow::Borrowed(t.name().unwrap()))),
+                .map(|t| Type::NonNullNamed(t.name().unwrap().into())),
             Definition::Operation(Spanning {
                 item:
                     Operation {
@@ -71,7 +69,7 @@ where
             }) => ctx
                 .schema
                 .concrete_subscription_type()
-                .map(|t| Type::NonNullNamed(Cow::Borrowed(t.name().unwrap()))),
+                .map(|t| Type::NonNullNamed(t.name().unwrap().into())),
         };
 
         ctx.with_pushed_type(def_type.as_ref(), |ctx| {
@@ -132,9 +130,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), |ctx| {
                 v.enter_variable_definition(ctx, def);
 
                 if let Some(ref default_value) = def.1.default_value {
@@ -185,7 +183,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<Argument<'a, S>>>,
+    meta_args: Option<&'a Vec<Argument<S>>>,
     arguments: &'a Option<Spanning<Arguments<S>>>,
 ) where
     S: ScalarValue,
@@ -307,10 +305,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(&Type::NonNullNamed(type_name.into())), visit_fn);
     } else {
         visit_fn(ctx);
     }
@@ -331,8 +326,8 @@ 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 {
+                        Type::NonNullNamed(name) | Type::Named(name) => {
                             ctx.schema.concrete_type_by_name(name)
                         }
                         _ => None,
@@ -348,14 +343,12 @@ 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 {
+                Type::List(inner, _) | Type::NonNullList(inner, _) => Some(&**inner),
                 _ => 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 17f72d40f..7dd764fd0 100644
--- a/juniper_actix/examples/subscription.rs
+++ b/juniper_actix/examples/subscription.rs
@@ -18,7 +18,7 @@ use juniper::{
 use juniper_actix::{graphiql_handler, graphql_handler, playground_handler, subscriptions};
 use juniper_graphql_ws::ConnectionConfig;
 
-type Schema = RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
+type Schema = RootNode<Query, EmptyMutation<Database>, Subscription>;
 
 fn schema() -> Schema {
     Schema::new(Query, EmptyMutation::<Database>::new(), Subscription)
diff --git a/juniper_actix/src/lib.rs b/juniper_actix/src/lib.rs
index 4e8e63315..d7324fc38 100644
--- a/juniper_actix/src/lib.rs
+++ b/juniper_actix/src/lib.rs
@@ -42,7 +42,7 @@ where
 
 /// Actix Web GraphQL Handler for GET and POST requests
 pub async fn graphql_handler<Query, Mutation, Subscription, CtxT, S>(
-    schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
+    schema: &juniper::RootNode<Query, Mutation, Subscription, S>,
     context: &CtxT,
     req: HttpRequest,
     payload: actix_web::web::Payload,
@@ -65,7 +65,7 @@ where
 }
 /// Actix GraphQL Handler for GET requests
 pub async fn get_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
-    schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
+    schema: &juniper::RootNode<Query, Mutation, Subscription, S>,
     context: &CtxT,
     req: HttpRequest,
 ) -> Result<HttpResponse, Error>
@@ -94,7 +94,7 @@ where
 
 /// Actix GraphQL Handler for POST requests
 pub async fn post_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
-    schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
+    schema: &juniper::RootNode<Query, Mutation, Subscription, S>,
     context: &CtxT,
     req: HttpRequest,
     payload: actix_web::web::Payload,
@@ -195,7 +195,7 @@ pub mod subscriptions {
     pub async fn ws_handler<Query, Mutation, Subscription, CtxT, S, I>(
         req: HttpRequest,
         stream: web::Payload,
-        schema: Arc<RootNode<'static, Query, Mutation, Subscription, S>>,
+        schema: Arc<RootNode<Query, Mutation, Subscription, S>>,
         init: I,
     ) -> Result<HttpResponse, actix_web::Error>
     where
@@ -238,7 +238,7 @@ pub mod subscriptions {
     pub async fn graphql_ws_handler<Query, Mutation, Subscription, CtxT, S, I>(
         req: HttpRequest,
         stream: web::Payload,
-        schema: Arc<RootNode<'static, Query, Mutation, Subscription, S>>,
+        schema: Arc<RootNode<Query, Mutation, Subscription, S>>,
         init: I,
     ) -> Result<HttpResponse, actix_web::Error>
     where
@@ -306,7 +306,7 @@ pub mod subscriptions {
     pub async fn graphql_transport_ws_handler<Query, Mutation, Subscription, CtxT, S, I>(
         req: HttpRequest,
         stream: web::Payload,
-        schema: Arc<RootNode<'static, Query, Mutation, Subscription, S>>,
+        schema: Arc<RootNode<Query, Mutation, Subscription, S>>,
         init: I,
     ) -> Result<HttpResponse, actix_web::Error>
     where
@@ -461,8 +461,7 @@ mod tests {
 
     use super::*;
 
-    type Schema =
-        juniper::RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
+    type Schema = juniper::RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
     async fn take_response_body_string(resp: ServiceResponse) -> String {
         let mut body = resp.into_body();
@@ -856,7 +855,7 @@ mod subscription_tests {
         }
     }
 
-    type Schema = juniper::RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
+    type Schema = juniper::RootNode<Query, EmptyMutation<Database>, Subscription>;
 
     fn subscription(
         proto: &'static str,
diff --git a/juniper_axum/examples/custom.rs b/juniper_axum/examples/custom.rs
index ec3bd3c75..b961e4e4b 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<Database>, Subscription>;
+type Schema = RootNode<Query, EmptyMutation<Database>, Subscription>;
 
 async fn homepage() -> Html<&'static str> {
     "<html><h1>juniper_axum/custom example</h1>\
diff --git a/juniper_axum/examples/simple.rs b/juniper_axum/examples/simple.rs
index 0250714a7..f1aa9e09c 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<Query, EmptyMutation, Subscription>;
 
 async fn homepage() -> Html<&'static str> {
     "<html><h1>juniper_axum/simple example</h1>\
diff --git a/juniper_axum/src/extract.rs b/juniper_axum/src/extract.rs
index fe087f672..50dedcead 100644
--- a/juniper_axum/src/extract.rs
+++ b/juniper_axum/src/extract.rs
@@ -44,7 +44,7 @@ use serde::Deserialize;
 ///     }
 /// }
 ///
-/// type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
+/// type Schema = RootNode<Query, EmptyMutation<Context>, EmptySubscription<Context>>;
 ///
 /// let schema = Schema::new(
 ///    Query,
diff --git a/juniper_axum/src/lib.rs b/juniper_axum/src/lib.rs
index 205669a67..633467102 100644
--- a/juniper_axum/src/lib.rs
+++ b/juniper_axum/src/lib.rs
@@ -52,7 +52,7 @@ pub use self::subscriptions::{graphql_transport_ws, graphql_ws, ws};
 ///     }
 /// }
 ///
-/// type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
+/// type Schema = RootNode<Query, EmptyMutation<Context>, EmptySubscription<Context>>;
 ///
 /// let schema = Schema::new(
 ///    Query,
diff --git a/juniper_axum/src/subscriptions.rs b/juniper_axum/src/subscriptions.rs
index cc1ec7d70..4568e6406 100644
--- a/juniper_axum/src/subscriptions.rs
+++ b/juniper_axum/src/subscriptions.rs
@@ -47,7 +47,7 @@ use juniper_graphql_ws::{graphql_transport_ws, graphql_ws, Init, Schema};
 /// use tokio::time::interval;
 /// use tokio_stream::wrappers::IntervalStream;
 ///
-/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>;
+/// type Schema = RootNode<Query, EmptyMutation, Subscription>;
 ///
 /// #[derive(Clone, Copy, Debug)]
 /// pub struct Query;
@@ -133,7 +133,7 @@ pub fn ws<S: Schema>(
 /// use tokio::time::interval;
 /// use tokio_stream::wrappers::IntervalStream;
 ///
-/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>;
+/// type Schema = RootNode<Query, EmptyMutation, Subscription>;
 ///
 /// #[derive(Clone, Copy, Debug)]
 /// pub struct Query;
@@ -225,7 +225,7 @@ pub fn graphql_transport_ws<S: Schema>(
 /// use tokio::time::interval;
 /// use tokio_stream::wrappers::IntervalStream;
 ///
-/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>;
+/// type Schema = RootNode<Query, EmptyMutation, Subscription>;
 ///
 /// #[derive(Clone, Copy, Debug)]
 /// pub struct Query;
@@ -317,7 +317,7 @@ pub fn graphql_ws<S: Schema>(
 /// use tokio::time::interval;
 /// use tokio_stream::wrappers::IntervalStream;
 ///
-/// type Schema = RootNode<'static, Query, EmptyMutation, Subscription>;
+/// type Schema = RootNode<Query, EmptyMutation, Subscription>;
 ///
 /// #[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<Query, EmptyMutation, Subscription>;
 ///
 /// #[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<Query, EmptyMutation, Subscription>;
 ///
 /// #[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 0e13ca2dd..e3548042b 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<Database>, EmptySubscription<Database>>;
+type Schema = RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
 struct TestApp(Router);
 
diff --git a/juniper_axum/tests/ws_test_suite.rs b/juniper_axum/tests/ws_test_suite.rs
index 01bc071e4..81f5c0b21 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::{connect_async, tungstenite::Message, MaybeTlsStream, WebSocketStream};
 
-type Schema = RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
+type Schema = RootNode<Query, EmptyMutation<Database>, Subscription>;
 
 #[derive(Clone)]
 struct TestApp(Router);
diff --git a/juniper_codegen/src/common/deprecation.rs b/juniper_codegen/src/common/deprecation.rs
index f213659c4..0bddc6c23 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 c3c5deaee..4f7b44f27 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 19fc184cf..539f8a3d6 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 092967f72..dec7aa155 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 048f6373e..a9a1f7c29 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> {
                     <Self as ::juniper::GraphQLType<#scalar>>::name(info)
                 }
 
diff --git a/juniper_codegen/src/graphql_input_object/mod.rs b/juniper_codegen/src/graphql_input_object/mod.rs
index baa091a0b..5a6853d6e 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> {
                     <Self as ::juniper::GraphQLType<#scalar>>::name(info)
                 }
             }
diff --git a/juniper_codegen/src/graphql_interface/mod.rs b/juniper_codegen/src/graphql_interface/mod.rs
index c618af84f..239f6ca07 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> {
                     <Self as ::juniper::GraphQLType<#scalar>>::name(info)
                 }
 
diff --git a/juniper_codegen/src/graphql_object/mod.rs b/juniper_codegen/src/graphql_object/mod.rs
index 96e18bb89..462f64c23 100644
--- a/juniper_codegen/src/graphql_object/mod.rs
+++ b/juniper_codegen/src/graphql_object/mod.rs
@@ -457,18 +457,14 @@ impl<Operation: ?Sized + 'static> Definition<Operation> {
             #[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<Query> {
                 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> {
                     <Self as ::juniper::GraphQLType<#scalar>>::name(info)
                 }
 
diff --git a/juniper_codegen/src/graphql_scalar/mod.rs b/juniper_codegen/src/graphql_scalar/mod.rs
index e296b05ae..cf915b614 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::<Self>(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> {
                     <Self as ::juniper::GraphQLType<#scalar>>::name(info)
                 }
 
diff --git a/juniper_codegen/src/graphql_subscription/mod.rs b/juniper_codegen/src/graphql_subscription/mod.rs
index 47af4b30a..38963bb5b 100644
--- a/juniper_codegen/src/graphql_subscription/mod.rs
+++ b/juniper_codegen/src/graphql_subscription/mod.rs
@@ -49,10 +49,10 @@ impl Definition<Subscription> {
                 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> {
                     <Self as ::juniper::GraphQLType<#scalar>>::name(info)
                 }
 
diff --git a/juniper_codegen/src/graphql_union/mod.rs b/juniper_codegen/src/graphql_union/mod.rs
index a89976234..93ad153ad 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> {
                     <Self as ::juniper::GraphQLType<#scalar>>::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 8553c189a..44aa02bd0 100644
--- a/juniper_graphql_ws/src/graphql_transport_ws/mod.rs
+++ b/juniper_graphql_ws/src/graphql_transport_ws/mod.rs
@@ -682,7 +682,7 @@ mod test {
     type ClientMessage = super::ClientMessage<DefaultScalarValue>;
     type ServerMessage = super::ServerMessage<DefaultScalarValue>;
 
-    fn new_test_schema() -> Arc<RootNode<'static, Query, EmptyMutation<Context>, Subscription>> {
+    fn new_test_schema() -> Arc<RootNode<Query, EmptyMutation<Context>, 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 87950717b..d648570ba 100644
--- a/juniper_graphql_ws/src/graphql_ws/mod.rs
+++ b/juniper_graphql_ws/src/graphql_ws/mod.rs
@@ -618,7 +618,7 @@ mod test {
     type ClientMessage = super::ClientMessage<DefaultScalarValue>;
     type ServerMessage = super::ServerMessage<DefaultScalarValue>;
 
-    fn new_test_schema() -> Arc<RootNode<'static, Query, EmptyMutation<Context>, Subscription>> {
+    fn new_test_schema() -> Arc<RootNode<Query, EmptyMutation<Context>, 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<Self::Query, Self::Mutation, Self::Subscription, Self::ScalarValue>;
 }
 
 /// 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<QueryT, MutationT, SubscriptionT, CtxT, S>(
-    pub Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
+    pub Arc<RootNode<QueryT, MutationT, SubscriptionT, S>>,
 )
 where
     QueryT: GraphQLTypeAsync<S, Context = CtxT> + 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<QueryT, MutationT, SubscriptionT, S> {
         &self.0
     }
 }
 
 impl<QueryT, MutationT, SubscriptionT, CtxT, S> Schema
-    for Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>
+    for Arc<RootNode<QueryT, MutationT, SubscriptionT, S>>
 where
     QueryT: GraphQLTypeAsync<S, Context = CtxT> + 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<QueryT, MutationT, SubscriptionT, S> {
         self
     }
 }
diff --git a/juniper_hyper/src/lib.rs b/juniper_hyper/src/lib.rs
index d39696301..31cf480b9 100644
--- a/juniper_hyper/src/lib.rs
+++ b/juniper_hyper/src/lib.rs
@@ -16,7 +16,7 @@ use serde_json::error::Error as SerdeError;
 use url::form_urlencoded;
 
 pub async fn graphql_sync<CtxT, QueryT, MutationT, SubscriptionT, S>(
-    root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
+    root_node: Arc<RootNode<QueryT, MutationT, SubscriptionT, S>>,
     context: Arc<CtxT>,
     req: Request<body::Incoming>,
 ) -> Response<String>
@@ -37,7 +37,7 @@ where
 }
 
 pub async fn graphql<CtxT, QueryT, MutationT, SubscriptionT, S>(
-    root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
+    root_node: Arc<RootNode<QueryT, MutationT, SubscriptionT, S>>,
     context: Arc<CtxT>,
     req: Request<body::Incoming>,
 ) -> Response<String>
@@ -150,7 +150,7 @@ fn render_error(err: GraphQLRequestError) -> Response<String> {
 }
 
 async fn execute_request_sync<CtxT, QueryT, MutationT, SubscriptionT, S>(
-    root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
+    root_node: Arc<RootNode<QueryT, MutationT, SubscriptionT, S>>,
     context: Arc<CtxT>,
     request: GraphQLBatchRequest<S>,
 ) -> Response<String>
@@ -181,7 +181,7 @@ where
 }
 
 async fn execute_request<CtxT, QueryT, MutationT, SubscriptionT, S>(
-    root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
+    root_node: Arc<RootNode<QueryT, MutationT, SubscriptionT, S>>,
     context: Arc<CtxT>,
     request: GraphQLBatchRequest<S>,
 ) -> Response<String>
diff --git a/juniper_rocket/examples/simple.rs b/juniper_rocket/examples/simple.rs
index f3a6d905a..1fd543ef2 100644
--- a/juniper_rocket/examples/simple.rs
+++ b/juniper_rocket/examples/simple.rs
@@ -4,7 +4,7 @@ use juniper::{
 };
 use rocket::{response::content::RawHtml, routes, State};
 
-type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
+type Schema = RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
 #[rocket::get("/")]
 async fn homepage() -> RawHtml<&'static str> {
diff --git a/juniper_rocket/src/lib.rs b/juniper_rocket/src/lib.rs
index 934047d17..267a66beb 100644
--- a/juniper_rocket/src/lib.rs
+++ b/juniper_rocket/src/lib.rs
@@ -31,7 +31,7 @@ use juniper::{
 /// };
 /// use rocket::{routes, State};
 ///
-/// type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
+/// type Schema = RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 ///
 /// // GET request accepts query parameters like these:
 /// // ?query=<urlencoded-graphql-query-string>
@@ -166,7 +166,7 @@ where
     /// Asynchronously execute an incoming GraphQL query.
     pub async fn execute<CtxT, QueryT, MutationT, SubscriptionT>(
         &self,
-        root_node: &RootNode<'_, QueryT, MutationT, SubscriptionT, S>,
+        root_node: &RootNode<QueryT, MutationT, SubscriptionT, S>,
         context: &CtxT,
     ) -> GraphQLResponse
     where
@@ -212,7 +212,7 @@ impl GraphQLResponse {
     /// # use juniper::tests::fixtures::starwars::schema::{Database, Query};
     /// # use juniper::{EmptyMutation, EmptySubscription, FieldError, RootNode, Value};
     /// #
-    /// # type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
+    /// # type Schema = RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
     /// #
     /// #[rocket::get("/graphql?<request..>")]
     /// fn get_graphql_handler(
diff --git a/juniper_rocket/tests/http_test_suite.rs b/juniper_rocket/tests/http_test_suite.rs
index 3e7ca823d..5398bb0c2 100644
--- a/juniper_rocket/tests/http_test_suite.rs
+++ b/juniper_rocket/tests/http_test_suite.rs
@@ -12,7 +12,7 @@ use rocket::{
     post, routes, Build, Rocket, State,
 };
 
-type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
+type Schema = RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
 fn bootstrap_rocket() -> Rocket<Build> {
     Rocket::build().manage(Database::new()).manage(Schema::new(
diff --git a/juniper_subscriptions/CHANGELOG.md b/juniper_subscriptions/CHANGELOG.md
index b59b6c626..c97ae3cbe 100644
--- a/juniper_subscriptions/CHANGELOG.md
+++ b/juniper_subscriptions/CHANGELOG.md
@@ -6,6 +6,18 @@ All user visible changes to `juniper_subscriptions` crate will be documented in
 
 
 
+## master
+
+### BC Breaks
+
+- Removed lifetime parameters from `Coordinator`. ([#1247], [#819])
+
+[#819]: /../../issues/819
+[#1247]: /../../pull/1247
+
+
+
+
 ## [0.17.0] · 2024-03-20
 [0.17.0]: /../../tree/juniper_subscriptions-v0.17.0/juniper_subscriptions
 
diff --git a/juniper_subscriptions/examples/basic.rs b/juniper_subscriptions/examples/basic.rs
index df5236744..aa92f703c 100644
--- a/juniper_subscriptions/examples/basic.rs
+++ b/juniper_subscriptions/examples/basic.rs
@@ -42,7 +42,7 @@ impl Subscription {
     }
 }
 
-type Schema = RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
+type Schema = RootNode<Query, EmptyMutation<Database>, 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 83d44126c..4875663d8 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<QueryT, MutationT, SubscriptionT, CtxT, S>
 where
     QueryT: GraphQLTypeAsync<S, Context = CtxT> + 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<QueryT, MutationT, SubscriptionT, S>,
 }
 
-impl<'a, QueryT, MutationT, SubscriptionT, CtxT, S>
-    Coordinator<'a, QueryT, MutationT, SubscriptionT, CtxT, S>
+impl<QueryT, MutationT, SubscriptionT, CtxT, S>
+    Coordinator<QueryT, MutationT, SubscriptionT, CtxT, S>
 where
     QueryT: GraphQLTypeAsync<S, Context = CtxT> + 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<QueryT, MutationT, SubscriptionT, S>) -> 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<QueryT, MutationT, SubscriptionT, CtxT, S>
 where
     QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send,
     QueryT::TypeInfo: Send + Sync,
diff --git a/juniper_warp/examples/subscription.rs b/juniper_warp/examples/subscription.rs
index 8ceb9049a..e4a18a336 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<Context>, Subscription>;
+type Schema = RootNode<Query, EmptyMutation<Context>, 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 f0f5bda0d..3c9d0d3e1 100644
--- a/juniper_warp/src/lib.rs
+++ b/juniper_warp/src/lib.rs
@@ -149,7 +149,7 @@ use self::response::JuniperResponse;
 ///
 /// [1]: https://github.com/seanmonstar/warp/issues/388#issuecomment-576453485
 pub fn make_graphql_filter<S, Query, Mutation, Subscription, CtxT, CtxErr>(
-    schema: impl Into<Arc<juniper::RootNode<'static, Query, Mutation, Subscription, S>>>,
+    schema: impl Into<Arc<juniper::RootNode<Query, Mutation, Subscription, S>>>,
     context_extractor: impl Filter<Extract = (CtxT,), Error = CtxErr> + Send + Sync + 'static,
 ) -> impl Filter<Extract = (reply::Response,), Error = Rejection> + Clone + Send
 where
@@ -192,7 +192,7 @@ where
 ///
 /// [1]: GraphQLBatchRequest::execute_sync
 pub fn make_graphql_filter_sync<S, Query, Mutation, Subscription, CtxT, CtxErr>(
-    schema: impl Into<Arc<juniper::RootNode<'static, Query, Mutation, Subscription, S>>>,
+    schema: impl Into<Arc<juniper::RootNode<Query, Mutation, Subscription, S>>>,
     context_extractor: impl Filter<Extract = (CtxT,), Error = CtxErr> + Send + Sync + 'static,
 ) -> impl Filter<Extract = (reply::Response,), Error = Rejection> + Clone + Send
 where
@@ -232,7 +232,7 @@ where
 /// `context`.
 async fn graphql_handler<Query, Mutation, Subscription, CtxT, S>(
     req: GraphQLBatchRequest<S>,
-    schema: Arc<juniper::RootNode<'static, Query, Mutation, Subscription, S>>,
+    schema: Arc<juniper::RootNode<Query, Mutation, Subscription, S>>,
     context: CtxT,
 ) -> reply::Response
 where
@@ -254,7 +254,7 @@ where
 /// [1]: GraphQLBatchRequest::execute_sync
 async fn graphql_handler_sync<Query, Mutation, Subscription, CtxT, S>(
     req: GraphQLBatchRequest<S>,
-    schema: Arc<juniper::RootNode<'static, Query, Mutation, Subscription, S>>,
+    schema: Arc<juniper::RootNode<Query, Mutation, Subscription, S>>,
     context: CtxT,
 ) -> reply::Response
 where
@@ -472,12 +472,8 @@ mod tests {
 
         #[tokio::test]
         async fn post_json() {
-            type Schema = juniper::RootNode<
-                'static,
-                Query,
-                EmptyMutation<Database>,
-                EmptySubscription<Database>,
-            >;
+            type Schema =
+                juniper::RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
             let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new());
 
@@ -522,12 +518,8 @@ mod tests {
                 }
             }
 
-            type Schema = juniper::RootNode<
-                'static,
-                Query,
-                EmptyMutation<Database>,
-                EmptySubscription<Database>,
-            >;
+            type Schema =
+                juniper::RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
             let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new());
 
@@ -570,12 +562,8 @@ mod tests {
 
         #[tokio::test]
         async fn batch_requests() {
-            type Schema = juniper::RootNode<
-                'static,
-                Query,
-                EmptyMutation<Database>,
-                EmptySubscription<Database>,
-            >;
+            type Schema =
+                juniper::RootNode<Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
             let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new());
 
diff --git a/juniper_warp/src/subscriptions.rs b/juniper_warp/src/subscriptions.rs
index 6511c235f..ba914d264 100644
--- a/juniper_warp/src/subscriptions.rs
+++ b/juniper_warp/src/subscriptions.rs
@@ -177,7 +177,7 @@ impl From<Infallible> 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<Query, Mutation, Subscription, CtxT, S, I>(
-    schema: impl Into<Arc<RootNode<'static, Query, Mutation, Subscription, S>>>,
+    schema: impl Into<Arc<RootNode<Query, Mutation, Subscription, S>>>,
     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<Query, Mutation, Subscription, CtxT, S, I>(
     websocket: warp::ws::WebSocket,
-    root_node: Arc<RootNode<'static, Query, Mutation, Subscription, S>>,
+    root_node: Arc<RootNode<Query, Mutation, Subscription, S>>,
     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<Query, Mutation, Subscription, CtxT, S, I>(
     websocket: warp::ws::WebSocket,
-    root_node: Arc<RootNode<'static, Query, Mutation, Subscription, S>>,
+    root_node: Arc<RootNode<Query, Mutation, Subscription, S>>,
     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 40ef4e904..cc81d2289 100644
--- a/tests/codegen/fail/input-object/derive_incompatible_field_type.stderr
+++ b/tests/codegen/fail/input-object/derive_incompatible_field_type.stderr
@@ -34,14 +34,14 @@ error[E0277]: the trait bound `ObjectA: FromInputValue<__S>` is not satisfied
              <Arc<T> as FromInputValue<S>>
              <Vec<T> as FromInputValue<S>>
            and $N others
-note: required by a bound in `Registry::<'r, S>::arg`
+note: required by a bound in `Registry::<S>::arg`
   --> $WORKSPACE/juniper/src/executor/mod.rs
    |
-   |     pub fn arg<T>(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S>
+   |     pub fn arg<T>(&mut self, name: ArcStr, info: &T::TypeInfo) -> Argument<S>
    |            --- required by a bound in this associated function
    |     where
    |         T: GraphQLType<S> + FromInputValue<S>,
-   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg`
+   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<S>::arg`
 
 error[E0277]: the trait bound `ObjectA: FromInputValue<__S>` is not satisfied
  --> fail/input-object/derive_incompatible_field_type.rs:8:10
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 df6701eb5..5719976c1 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
@@ -8,9 +8,9 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
             <bool as IsOutputType<__S>>
             <i32 as IsOutputType<__S>>
             <f64 as IsOutputType<__S>>
+            <ArcStr as IsOutputType<S>>
             <CharacterValueEnum as IsOutputType<__S>>
             <Box<T> as IsOutputType<S>>
-            <juniper::meta::Field<'a, S> as IsOutputType<S>>
-            <Argument<'a, S> as IsOutputType<S>>
-            <EnumValue as IsOutputType<__S>>
+            <juniper::meta::Field<S> as IsOutputType<S>>
+            <Argument<S> as IsOutputType<S>>
           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 9251365be..f5804cbe3 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
@@ -8,9 +8,9 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
             <bool as IsOutputType<__S>>
             <i32 as IsOutputType<__S>>
             <f64 as IsOutputType<__S>>
+            <ArcStr as IsOutputType<S>>
             <CharacterValueEnum as IsOutputType<__S>>
             <Box<T> as IsOutputType<S>>
-            <juniper::meta::Field<'a, S> as IsOutputType<S>>
-            <Argument<'a, S> as IsOutputType<S>>
-            <EnumValue as IsOutputType<__S>>
+            <juniper::meta::Field<S> as IsOutputType<S>>
+            <Argument<S> as IsOutputType<S>>
           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 a72e3015a..ebf6dc3a2 100644
--- a/tests/codegen/fail/interface/trait/argument_non_input_type.stderr
+++ b/tests/codegen/fail/interface/trait/argument_non_input_type.stderr
@@ -34,11 +34,11 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied
              <Vec<T> as FromInputValue<S>>
              <TypeKind as FromInputValue<__S>>
            and $N others
-note: required by a bound in `Registry::<'r, S>::arg`
+note: required by a bound in `Registry::<S>::arg`
   --> $WORKSPACE/juniper/src/executor/mod.rs
    |
-   |     pub fn arg<T>(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S>
+   |     pub fn arg<T>(&mut self, name: ArcStr, info: &T::TypeInfo) -> Argument<S>
    |            --- required by a bound in this associated function
    |     where
    |         T: GraphQLType<S> + FromInputValue<S>,
-   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg`
+   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<S>::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 f15bd4353..5e2d20af3 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
@@ -8,9 +8,9 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
             <bool as IsOutputType<__S>>
             <i32 as IsOutputType<__S>>
             <f64 as IsOutputType<__S>>
+            <ArcStr as IsOutputType<S>>
             <CharacterValueEnum as IsOutputType<__S>>
             <Box<T> as IsOutputType<S>>
-            <juniper::meta::Field<'a, S> as IsOutputType<S>>
-            <Argument<'a, S> as IsOutputType<S>>
-            <EnumValue as IsOutputType<__S>>
+            <juniper::meta::Field<S> as IsOutputType<S>>
+            <Argument<S> as IsOutputType<S>>
           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 cb8c0e1d8..9faed0675 100644
--- a/tests/codegen/fail/object/argument_non_input_type.stderr
+++ b/tests/codegen/fail/object/argument_non_input_type.stderr
@@ -34,14 +34,14 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied
              <Vec<T> as FromInputValue<S>>
              <TypeKind as FromInputValue<__S>>
            and $N others
-note: required by a bound in `Registry::<'r, S>::arg`
+note: required by a bound in `Registry::<S>::arg`
   --> $WORKSPACE/juniper/src/executor/mod.rs
    |
-   |     pub fn arg<T>(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S>
+   |     pub fn arg<T>(&mut self, name: ArcStr, info: &T::TypeInfo) -> Argument<S>
    |            --- required by a bound in this associated function
    |     where
    |         T: GraphQLType<S> + FromInputValue<S>,
-   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg`
+   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<S>::arg`
 
 error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied
   --> fail/object/argument_non_input_type.rs:10:1
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 df4b4c650..21e18edcd 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
@@ -9,8 +9,8 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
              <i32 as IsOutputType<__S>>
              <f64 as IsOutputType<__S>>
              <ObjA as IsOutputType<__S>>
+             <ArcStr as IsOutputType<S>>
              <Box<T> as IsOutputType<S>>
-             <juniper::meta::Field<'a, S> as IsOutputType<S>>
-             <Argument<'a, S> as IsOutputType<S>>
-             <EnumValue as IsOutputType<__S>>
+             <juniper::meta::Field<S> as IsOutputType<S>>
+             <Argument<S> as IsOutputType<S>>
            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 aa3628e71..de38f71ea 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
@@ -8,9 +8,9 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
             <bool as IsOutputType<__S>>
             <i32 as IsOutputType<__S>>
             <f64 as IsOutputType<__S>>
+            <ArcStr as IsOutputType<S>>
             <ObjA as IsOutputType<__S>>
             <Box<T> as IsOutputType<S>>
-            <juniper::meta::Field<'a, S> as IsOutputType<S>>
-            <Argument<'a, S> as IsOutputType<S>>
-            <EnumValue as IsOutputType<__S>>
+            <juniper::meta::Field<S> as IsOutputType<S>>
+            <Argument<S> as IsOutputType<S>>
           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 be23f0add..66ec8fd9d 100644
--- a/tests/codegen/fail/subscription/argument_non_input_type.stderr
+++ b/tests/codegen/fail/subscription/argument_non_input_type.stderr
@@ -42,14 +42,14 @@ error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied
              <Vec<T> as FromInputValue<S>>
              <TypeKind as FromInputValue<__S>>
            and $N others
-note: required by a bound in `Registry::<'r, S>::arg`
+note: required by a bound in `Registry::<S>::arg`
   --> $WORKSPACE/juniper/src/executor/mod.rs
    |
-   |     pub fn arg<T>(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r, S>
+   |     pub fn arg<T>(&mut self, name: ArcStr, info: &T::TypeInfo) -> Argument<S>
    |            --- required by a bound in this associated function
    |     where
    |         T: GraphQLType<S> + FromInputValue<S>,
-   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg`
+   |                             ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<S>::arg`
 
 error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied
   --> fail/subscription/argument_non_input_type.rs:15:1
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 984db7003..12040152e 100644
--- a/tests/codegen/fail/subscription/field_non_output_return_type.stderr
+++ b/tests/codegen/fail/subscription/field_non_output_return_type.stderr
@@ -9,8 +9,8 @@ error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
              <i32 as IsOutputType<__S>>
              <f64 as IsOutputType<__S>>
              <ObjA as IsOutputType<__S>>
+             <ArcStr as IsOutputType<S>>
              <Box<T> as IsOutputType<S>>
-             <juniper::meta::Field<'a, S> as IsOutputType<S>>
-             <Argument<'a, S> as IsOutputType<S>>
-             <EnumValue as IsOutputType<__S>>
+             <juniper::meta::Field<S> as IsOutputType<S>>
+             <Argument<S> as IsOutputType<S>>
            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 c0356aa36..1bc95b3b1 100644
--- a/tests/codegen/fail/union/enum_non_object_variant.stderr
+++ b/tests/codegen/fail/union/enum_non_object_variant.stderr
@@ -6,11 +6,11 @@ error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied
    |
    = help: the following other types implement trait `GraphQLObject<S>`:
              <Box<T> as GraphQLObject<S>>
-             <juniper::meta::Field<'a, S> as GraphQLObject<S>>
-             <Argument<'a, S> as GraphQLObject<S>>
+             <juniper::meta::Field<S> as GraphQLObject<S>>
+             <Argument<S> as GraphQLObject<S>>
              <EnumValue as GraphQLObject<__S>>
-             <SchemaType<'a, S> as GraphQLObject<S>>
+             <SchemaType<S> as GraphQLObject<S>>
              <juniper::schema::model::TypeType<'a, S> as GraphQLObject<S>>
-             <juniper::schema::model::DirectiveType<'a, S> as GraphQLObject<S>>
+             <juniper::schema::model::DirectiveType<S> as GraphQLObject<S>>
              <Arc<T> as GraphQLObject<S>>
              <&T as GraphQLObject<S>>
diff --git a/tests/codegen/fail/union/struct_non_object_variant.stderr b/tests/codegen/fail/union/struct_non_object_variant.stderr
index 934344c60..694553747 100644
--- a/tests/codegen/fail/union/struct_non_object_variant.stderr
+++ b/tests/codegen/fail/union/struct_non_object_variant.stderr
@@ -6,11 +6,11 @@ error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied
    |
    = help: the following other types implement trait `GraphQLObject<S>`:
              <Box<T> as GraphQLObject<S>>
-             <juniper::meta::Field<'a, S> as GraphQLObject<S>>
-             <Argument<'a, S> as GraphQLObject<S>>
+             <juniper::meta::Field<S> as GraphQLObject<S>>
+             <Argument<S> as GraphQLObject<S>>
              <EnumValue as GraphQLObject<__S>>
-             <SchemaType<'a, S> as GraphQLObject<S>>
+             <SchemaType<S> as GraphQLObject<S>>
              <juniper::schema::model::TypeType<'a, S> as GraphQLObject<S>>
-             <juniper::schema::model::DirectiveType<'a, S> as GraphQLObject<S>>
+             <juniper::schema::model::DirectiveType<S> as GraphQLObject<S>>
              <Arc<T> as GraphQLObject<S>>
              <&T as GraphQLObject<S>>
diff --git a/tests/codegen/fail/union/trait_non_object_variant.stderr b/tests/codegen/fail/union/trait_non_object_variant.stderr
index 602147594..98ef08320 100644
--- a/tests/codegen/fail/union/trait_non_object_variant.stderr
+++ b/tests/codegen/fail/union/trait_non_object_variant.stderr
@@ -6,11 +6,11 @@ error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied
    |
    = help: the following other types implement trait `GraphQLObject<S>`:
              <Box<T> as GraphQLObject<S>>
-             <juniper::meta::Field<'a, S> as GraphQLObject<S>>
-             <Argument<'a, S> as GraphQLObject<S>>
+             <juniper::meta::Field<S> as GraphQLObject<S>>
+             <Argument<S> as GraphQLObject<S>>
              <EnumValue as GraphQLObject<__S>>
-             <SchemaType<'a, S> as GraphQLObject<S>>
+             <SchemaType<S> as GraphQLObject<S>>
              <juniper::schema::model::TypeType<'a, S> as GraphQLObject<S>>
-             <juniper::schema::model::DirectiveType<'a, S> as GraphQLObject<S>>
+             <juniper::schema::model::DirectiveType<S> as GraphQLObject<S>>
              <Arc<T> as GraphQLObject<S>>
              <&T as GraphQLObject<S>>
diff --git a/tests/integration/tests/codegen_subscription_attr.rs b/tests/integration/tests/codegen_subscription_attr.rs
index e9ab167a2..f846dbfb1 100644
--- a/tests/integration/tests/codegen_subscription_attr.rs
+++ b/tests/integration/tests/codegen_subscription_attr.rs
@@ -30,25 +30,25 @@ impl Query {
     }
 }
 
-fn schema<'q, C, Qry, Sub>(
+fn schema<C, Qry, Sub>(
     query_root: Qry,
     subscription_root: Sub,
-) -> RootNode<'q, Qry, EmptyMutation<C>, Sub>
+) -> RootNode<Qry, EmptyMutation<C>, Sub>
 where
-    Qry: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q,
-    Sub: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q,
+    Qry: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()>,
+    Sub: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()>,
 {
     RootNode::new(query_root, EmptyMutation::<C>::new(), subscription_root)
 }
 
-fn schema_with_scalar<'q, S, C, Qry, Sub>(
+fn schema_with_scalar<S, C, Qry, Sub>(
     query_root: Qry,
     subscription_root: Sub,
-) -> RootNode<'q, Qry, EmptyMutation<C>, Sub, S>
+) -> RootNode<Qry, EmptyMutation<C>, Sub, S>
 where
-    Qry: GraphQLType<S, Context = C, TypeInfo = ()> + 'q,
-    Sub: GraphQLType<S, Context = C, TypeInfo = ()> + 'q,
-    S: ScalarValue + 'q,
+    Qry: GraphQLType<S, Context = C, TypeInfo = ()>,
+    Sub: GraphQLType<S, Context = C, TypeInfo = ()>,
+    S: ScalarValue,
 {
     RootNode::new_with_scalar_value(query_root, EmptyMutation::<C>::new(), subscription_root)
 }
diff --git a/tests/integration/tests/common/mod.rs b/tests/integration/tests/common/mod.rs
index aae6a04c0..1ce8b4417 100644
--- a/tests/integration/tests/common/mod.rs
+++ b/tests/integration/tests/common/mod.rs
@@ -11,11 +11,9 @@ pub mod util {
         GraphQLError, GraphQLType, RootNode, ScalarValue, Value, ValuesStream,
     };
 
-    pub fn schema<'q, C, Q>(
-        query_root: Q,
-    ) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>>
+    pub fn schema<C, Q>(query_root: Q) -> RootNode<Q, EmptyMutation<C>, EmptySubscription<C>>
     where
-        Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q,
+        Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()>,
     {
         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<S, C, Q>(
         query_root: Q,
-    ) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>, S>
+    ) -> RootNode<Q, EmptyMutation<C>, EmptySubscription<C>, S>
     where
-        Q: GraphQLType<S, Context = C, TypeInfo = ()> + 'q,
-        S: ScalarValue + 'q,
+        Q: GraphQLType<S, Context = C, TypeInfo = ()>,
+        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 332306a32..244145518 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<Query, EmptyMutation, EmptySubscription>;
 
 #[tokio::test]
 async fn test() {
diff --git a/tests/integration/tests/explicit_null.rs b/tests/integration/tests/explicit_null.rs
index 4c65f66c1..2aea8f5f4 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<Context>, EmptySubscription<Context>>;
+type Schema = juniper::RootNode<Query, EmptyMutation<Context>, EmptySubscription<Context>>;
 
 #[tokio::test]
 async fn explicit_null() {
diff --git a/tests/integration/tests/issue_371.rs b/tests/integration/tests/issue_371.rs
index 41f227e0b..bbad91541 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<Context>, EmptySubscription<Context>>;
+type Schema = RootNode<Query, EmptyMutation<Context>, EmptySubscription<Context>>;
 
 #[tokio::test]
 async fn users() {
diff --git a/tests/integration/tests/issue_398.rs b/tests/integration/tests/issue_398.rs
index 4fad2d125..ae08dbf14 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<Query, EmptyMutation<()>, 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 a8a4ef13c..266fd0399 100644
--- a/tests/integration/tests/issue_407.rs
+++ b/tests/integration/tests/issue_407.rs
@@ -42,7 +42,7 @@ impl Query {
     }
 }
 
-type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>;
+type Schema = juniper::RootNode<Query, EmptyMutation, EmptySubscription>;
 
 #[tokio::test]
 async fn fragments_in_interface() {
diff --git a/tests/integration/tests/issue_500.rs b/tests/integration/tests/issue_500.rs
index d56c797bb..d80eb661a 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<Query, EmptyMutation<()>, EmptySubscription<()>>;
 
 #[tokio::test]
 async fn nested_fragments() {
diff --git a/tests/integration/tests/issue_798.rs b/tests/integration/tests/issue_798.rs
index 402524063..c96066742 100644
--- a/tests/integration/tests/issue_798.rs
+++ b/tests/integration/tests/issue_798.rs
@@ -53,7 +53,7 @@ impl Query {
     }
 }
 
-type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>;
+type Schema = RootNode<Query, EmptyMutation, EmptySubscription>;
 
 #[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 4886f645b..2003cb469 100644
--- a/tests/integration/tests/issue_914.rs
+++ b/tests/integration/tests/issue_914.rs
@@ -34,7 +34,7 @@ impl Query {
     }
 }
 
-type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>;
+type Schema = juniper::RootNode<Query, EmptyMutation, EmptySubscription>;
 
 #[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 b592f392e..23c058f3d 100644
--- a/tests/integration/tests/issue_922.rs
+++ b/tests/integration/tests/issue_922.rs
@@ -45,7 +45,7 @@ struct Droid {
     pub name: String,
 }
 
-type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>;
+type Schema = juniper::RootNode<Query, EmptyMutation, EmptySubscription>;
 
 #[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 4f8fa9c7c..bdd8f3ea6 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<Query, EmptyMutation, SubscriptionsRoot>;
 
 #[tokio::test]
 async fn error_extensions() {
diff --git a/tests/integration/tests/issue_945.rs b/tests/integration/tests/issue_945.rs
index 424583138..c30cf7479 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<Query, EmptyMutation, EmptySubscription>;
 
 #[tokio::test]
 async fn fragment_on_union() {
diff --git a/tests/integration/tests/pre_parse.rs b/tests/integration/tests/pre_parse.rs
index 7d1c239c7..b27cf4754 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<Context>, Subscription>;
+type Schema = RootNode<Query, EmptyMutation<Context>, Subscription>;
 
 #[tokio::test]
 async fn query_document_can_be_pre_parsed() {