From 2d1e5d38b753859401ad634fddc0ecd75ad3da21 Mon Sep 17 00:00:00 2001
From: tyranron <tyranron@gmail.com>
Date: Fri, 22 Apr 2022 16:48:19 +0300
Subject: [PATCH] Impl some basic types

---
 juniper/src/executor/mod.rs    |  63 +++++++++
 juniper/src/graphql/mod.rs     |  55 ++++++++
 juniper/src/graphql/resolve.rs | 248 ++++++++++++++++++++++++++-------
 juniper/src/lib.rs             |   2 +-
 juniper/src/resolve/mod.rs     |  67 +++++++--
 juniper/src/types/arc.rs       | 186 +++++++++++++++++++++++++
 juniper/src/types/box.rs       | 184 ++++++++++++++++++++++++
 juniper/src/types/iter.rs      |  65 +++++++++
 juniper/src/types/mod.rs       |   9 ++
 juniper/src/types/option.rs    |  78 +++++++++++
 juniper/src/types/rc.rs        | 186 +++++++++++++++++++++++++
 juniper/src/types/ref.rs       | 182 ++++++++++++++++++++++++
 juniper/src/types/ref_mut.rs   | 182 ++++++++++++++++++++++++
 juniper/src/types/vec.rs       |  77 ++++++++++
 14 files changed, 1523 insertions(+), 61 deletions(-)
 create mode 100644 juniper/src/types/arc.rs
 create mode 100644 juniper/src/types/box.rs
 create mode 100644 juniper/src/types/iter.rs
 create mode 100644 juniper/src/types/option.rs
 create mode 100644 juniper/src/types/rc.rs
 create mode 100644 juniper/src/types/ref.rs
 create mode 100644 juniper/src/types/ref_mut.rs
 create mode 100644 juniper/src/types/vec.rs

diff --git a/juniper/src/executor/mod.rs b/juniper/src/executor/mod.rs
index cf35af15..23073222 100644
--- a/juniper/src/executor/mod.rs
+++ b/juniper/src/executor/mod.rs
@@ -17,6 +17,7 @@ use crate::{
         Selection, ToInputValue, Type,
     },
     parser::{SourcePosition, Spanning},
+    resolve,
     schema::{
         meta::{
             Argument, DeprecationStatus, EnumMeta, EnumValue, Field, InputObjectMeta,
@@ -83,6 +84,12 @@ where
     field_path: Arc<FieldPath<'a>>,
 }
 
+impl<'r, 'a, Ctx: ?Sized, S> Executor<'r, 'a, Ctx, S> {
+    pub(crate) fn current_type_new(&self) -> &TypeType<'a, S> {
+        &self.current_type
+    }
+}
+
 /// Error type for errors that occur during query execution
 ///
 /// All execution errors contain the source position in the query of the field
@@ -1183,6 +1190,32 @@ impl<'r, S: 'r> Registry<'r, S> {
         }
     }
 
+    /// Returns a [`Type`] meta information for the specified [`graphql::Type`],
+    /// registered in this [`Registry`].
+    ///
+    /// If this [`Registry`] doesn't contain a [`Type`] meta information with
+    /// such [`TypeName`] before, it will construct the one and store it.
+    ///
+    /// [`graphql::Type`]: resolve::Type
+    /// [`TypeName`]: resolve::TypeName
+    pub fn get_type_new<T, Info>(&mut self, info: &Info) -> Type<'r>
+    where
+        T: resolve::Type<Info, S> + resolve::TypeName<Info> + ?Sized,
+        Info: ?Sized,
+    {
+        let name = T::type_name(info);
+        let validated_name = name.parse::<Name>().unwrap();
+        if !self.types.contains_key(name) {
+            self.insert_placeholder(
+                validated_name.clone(),
+                Type::NonNullNamed(Cow::Owned(name.to_string())),
+            );
+            let meta = T::meta(self, info);
+            self.types.insert(validated_name, meta);
+        }
+        self.types[name].as_type()
+    }
+
     /// Creates a [`Field`] with the provided `name`.
     pub fn field<T>(&mut self, name: &str, info: &T::TypeInfo) -> Field<'r, S>
     where
@@ -1278,6 +1311,24 @@ impl<'r, S: 'r> Registry<'r, S> {
         ListMeta::new(of_type, expected_size)
     }
 
+    /// Builds a [`ListMeta`] information for the specified [`graphql::Type`].
+    ///
+    /// Specifying `expected_size` will be used in validation to ensure that
+    /// values of this type matches it.
+    ///
+    /// [`graphql::Type`]: resolve::Type
+    pub fn build_list_type_new<T, Info>(
+        &mut self,
+        info: &Info,
+        expected_size: Option<usize>,
+    ) -> ListMeta<'r>
+    where
+        T: resolve::Type<Info, S> + ?Sized,
+        Info: ?Sized,
+    {
+        ListMeta::new(T::meta(self, info).as_type(), expected_size)
+    }
+
     /// Creates a [`NullableMeta`] type.
     pub fn build_nullable_type<T>(&mut self, info: &T::TypeInfo) -> NullableMeta<'r>
     where
@@ -1288,6 +1339,18 @@ impl<'r, S: 'r> Registry<'r, S> {
         NullableMeta::new(of_type)
     }
 
+    /// Builds a [`NullableMeta`] information for the specified
+    /// [`graphql::Type`].
+    ///
+    /// [`graphql::Type`]: resolve::Type
+    pub fn build_nullable_type_new<T, Info>(&mut self, info: &Info) -> NullableMeta<'r>
+    where
+        T: resolve::Type<Info, S> + ?Sized,
+        Info: ?Sized,
+    {
+        NullableMeta::new(T::meta(self, info).as_type())
+    }
+
     /// Creates an [`ObjectMeta`] type with the given `fields`.
     pub fn build_object_type<T>(
         &mut self,
diff --git a/juniper/src/graphql/mod.rs b/juniper/src/graphql/mod.rs
index 581d1dcd..4d87480d 100644
--- a/juniper/src/graphql/mod.rs
+++ b/juniper/src/graphql/mod.rs
@@ -1 +1,56 @@
 pub mod resolve;
+
+use crate::DefaultScalarValue;
+
+pub use crate::value::Value;
+
+pub use self::resolve::Type;
+
+pub trait Interface<S = DefaultScalarValue>:
+    OutputType<S>
+    + Type<S>
+    + resolve::TypeName
+    + resolve::ConcreteTypeName
+    + resolve::Value<S>
+    + resolve::ValueAsync<S>
+    + resolve::ConcreteValue<S>
+    + resolve::ConcreteValueAsync<S>
+    + resolve::Field<S>
+    + resolve::FieldAsync<S>
+{
+    fn assert_interface();
+}
+
+pub trait Object<S = DefaultScalarValue>:
+    OutputType<S>
+    + Type<S>
+    + resolve::TypeName
+    + resolve::ConcreteTypeName
+    + resolve::Value<S>
+    + resolve::ValueAsync<S>
+    + resolve::Field<S>
+    + resolve::FieldAsync<S>
+{
+    fn assert_object();
+}
+
+pub trait Union<S = DefaultScalarValue>:
+    OutputType<S>
+    + Type<S>
+    + resolve::TypeName
+    + resolve::ConcreteTypeName
+    + resolve::Value<S>
+    + resolve::ValueAsync<S>
+    + resolve::ConcreteValue<S>
+    + resolve::ConcreteValueAsync<S>
+{
+    fn assert_union();
+}
+
+pub trait InputType<S = DefaultScalarValue> {
+    fn assert_input_type();
+}
+
+pub trait OutputType<S = DefaultScalarValue> {
+    fn assert_output_type();
+}
diff --git a/juniper/src/graphql/resolve.rs b/juniper/src/graphql/resolve.rs
index 068115a8..22fe5342 100644
--- a/juniper/src/graphql/resolve.rs
+++ b/juniper/src/graphql/resolve.rs
@@ -1,10 +1,25 @@
 use crate::{
-    executor::{ExecutionResult, Executor, Registry},
-    resolve,
-    schema::meta::MetaType,
-    Arguments, DefaultScalarValue,
+    meta::MetaType, resolve, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor,
+    Registry, Selection,
 };
 
+pub trait Type<S = DefaultScalarValue> {
+    fn meta<'r, Info: ?Sized>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+        Self: resolve::Type<Info, S>;
+}
+
+impl<T: ?Sized, S> Type<S> for T {
+    fn meta<'r, Info: ?Sized>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+        Self: resolve::Type<Info, S>,
+    {
+        <Self as resolve::Type<Info, S>>::meta(registry, info)
+    }
+}
+
 pub trait TypeName {
     fn type_name<Info: ?Sized>(info: &Info) -> &str
     where
@@ -20,52 +35,6 @@ impl<T: ?Sized> TypeName for T {
     }
 }
 
-pub trait Type<S = DefaultScalarValue> {
-    fn meta<'r, Info: ?Sized>(info: &Info, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-    where
-        S: 'r,
-        Self: resolve::Type<Info, S>;
-}
-
-impl<T: ?Sized, S> Type<S> for T {
-    fn meta<'r, Info: ?Sized>(info: &Info, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-    where
-        S: 'r,
-        Self: resolve::Type<Info, S>,
-    {
-        <Self as resolve::Type<Info, S>>::meta(info, registry)
-    }
-}
-
-pub trait Field<S = DefaultScalarValue> {
-    fn resolve_field<Info: ?Sized, Ctx: ?Sized>(
-        &self,
-        info: &Info,
-        field_name: &str,
-        arguments: &Arguments<S>,
-        executor: &Executor<Ctx, S>,
-    ) -> ExecutionResult<S>
-    where
-        Self: resolve::Field<Info, Ctx, S>;
-}
-
-impl<T: ?Sized, S> Field<S> for T {
-    fn resolve_field<Info: ?Sized, Ctx: ?Sized>(
-        &self,
-        info: &Info,
-        field_name: &str,
-        arguments: &Arguments<S>,
-        executor: &Executor<Ctx, S>,
-    ) -> ExecutionResult<S>
-    where
-        Self: resolve::Field<Info, Ctx, S>,
-    {
-        <Self as resolve::Field<Info, Ctx, S>>::resolve_field(
-            self, info, field_name, arguments, executor,
-        )
-    }
-}
-
 pub trait ConcreteTypeName {
     fn concrete_type_name<'i, Info: ?Sized>(&self, info: &'i Info) -> &'i str
     where
@@ -80,3 +49,182 @@ impl<T: ?Sized> ConcreteTypeName for T {
         <Self as resolve::ConcreteTypeName<Info>>::concrete_type_name(self, info)
     }
 }
+
+pub trait Value<S = DefaultScalarValue> {
+    fn resolve_value<Info: ?Sized, Ctx: ?Sized>(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>
+    where
+        Self: resolve::Value<Info, Ctx, S>;
+}
+
+impl<T: ?Sized, S> Value<S> for T {
+    fn resolve_value<Info: ?Sized, Ctx: ?Sized>(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>
+    where
+        Self: resolve::Value<Info, Ctx, S>,
+    {
+        <Self as resolve::Value<Info, Ctx, S>>::resolve_value(self, selection_set, info, executor)
+    }
+}
+
+pub trait ValueAsync<S = DefaultScalarValue> {
+    fn resolve_value_async<'r, Info: ?Sized, Ctx: ?Sized>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>
+    where
+        Self: resolve::ValueAsync<Info, Ctx, S>;
+}
+
+impl<T: ?Sized, S> ValueAsync<S> for T {
+    fn resolve_value_async<'r, Info: ?Sized, Ctx: ?Sized>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>
+    where
+        Self: resolve::ValueAsync<Info, Ctx, S>,
+    {
+        <Self as resolve::ValueAsync<Info, Ctx, S>>::resolve_value_async(
+            self,
+            selection_set,
+            info,
+            executor,
+        )
+    }
+}
+
+pub trait ConcreteValue<S = DefaultScalarValue> {
+    fn resolve_concrete_value<Info: ?Sized, Ctx: ?Sized>(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>
+    where
+        Self: resolve::ConcreteValue<Info, Ctx, S>;
+}
+
+impl<T: ?Sized, S> ConcreteValue<S> for T {
+    fn resolve_concrete_value<Info: ?Sized, Ctx: ?Sized>(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>
+    where
+        Self: resolve::ConcreteValue<Info, Ctx, S>,
+    {
+        <Self as resolve::ConcreteValue<Info, Ctx, S>>::resolve_concrete_value(
+            self,
+            type_name,
+            selection_set,
+            info,
+            executor,
+        )
+    }
+}
+
+pub trait ConcreteValueAsync<S = DefaultScalarValue> {
+    fn resolve_concrete_value_async<'r, Info: ?Sized, Ctx: ?Sized>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>
+    where
+        Self: resolve::ConcreteValueAsync<Info, Ctx, S>;
+}
+
+impl<T: ?Sized, S> ConcreteValueAsync<S> for T {
+    fn resolve_concrete_value_async<'r, Info: ?Sized, Ctx: ?Sized>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>
+    where
+        Self: resolve::ConcreteValueAsync<Info, Ctx, S>,
+    {
+        <Self as resolve::ConcreteValueAsync<Info, Ctx, S>>::resolve_concrete_value_async(
+            self,
+            type_name,
+            selection_set,
+            info,
+            executor,
+        )
+    }
+}
+
+pub trait Field<S = DefaultScalarValue> {
+    fn resolve_field<Info: ?Sized, Ctx: ?Sized>(
+        &self,
+        field_name: &str,
+        arguments: &Arguments<S>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>
+    where
+        Self: resolve::Field<Info, Ctx, S>;
+}
+
+impl<T: ?Sized, S> Field<S> for T {
+    fn resolve_field<Info: ?Sized, Ctx: ?Sized>(
+        &self,
+        field_name: &str,
+        arguments: &Arguments<S>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>
+    where
+        Self: resolve::Field<Info, Ctx, S>,
+    {
+        <Self as resolve::Field<Info, Ctx, S>>::resolve_field(
+            self, field_name, arguments, info, executor,
+        )
+    }
+}
+
+pub trait FieldAsync<S = DefaultScalarValue> {
+    fn resolve_field_async<'r, Info: ?Sized, Ctx: ?Sized>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>
+    where
+        Self: resolve::FieldAsync<Info, Ctx, S>;
+}
+
+impl<T: ?Sized, S> FieldAsync<S> for T {
+    fn resolve_field_async<'r, Info: ?Sized, Ctx: ?Sized>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>
+    where
+        Self: resolve::FieldAsync<Info, Ctx, S>,
+    {
+        <Self as resolve::FieldAsync<Info, Ctx, S>>::resolve_field_async(
+            self, field_name, arguments, info, executor,
+        )
+    }
+}
diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs
index fa869cbd..d9b4979c 100644
--- a/juniper/src/lib.rs
+++ b/juniper/src/lib.rs
@@ -41,7 +41,7 @@ pub(crate) mod schema;
 mod types;
 mod util;
 pub mod validation;
-mod value;
+pub(crate) mod value;
 
 #[cfg(all(test, not(feature = "expose-test-schema")))]
 mod tests;
diff --git a/juniper/src/resolve/mod.rs b/juniper/src/resolve/mod.rs
index 27b28a19..e027d0cf 100644
--- a/juniper/src/resolve/mod.rs
+++ b/juniper/src/resolve/mod.rs
@@ -1,29 +1,76 @@
 use crate::{
-    executor::{ExecutionResult, Executor, Registry},
-    schema::meta::MetaType,
-    Arguments, DefaultScalarValue,
+    meta::MetaType, Arguments, BoxFuture, DefaultScalarValue, ExecutionResult, Executor, Registry,
+    Selection,
 };
 
+pub trait Type<Info: ?Sized, S = DefaultScalarValue> {
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r;
+}
+
 pub trait TypeName<Info: ?Sized> {
     fn type_name(info: &Info) -> &str;
 }
 
-pub trait Type<Info: ?Sized, S = DefaultScalarValue> {
-    fn meta<'r>(info: &Info, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
-    where
-        S: 'r;
+pub trait ConcreteTypeName<Info: ?Sized> {
+    fn concrete_type_name<'i>(&self, info: &'i Info) -> &'i str;
+}
+
+pub trait Value<Info: ?Sized, Ctx: ?Sized, S = DefaultScalarValue> {
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>;
+}
+
+pub trait ValueAsync<Info: ?Sized, Ctx: ?Sized, S = DefaultScalarValue> {
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>;
+}
+
+pub trait ConcreteValue<Info: ?Sized, Ctx: ?Sized, S = DefaultScalarValue> {
+    fn resolve_concrete_value(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S>;
+}
+
+pub trait ConcreteValueAsync<Info: ?Sized, Ctx: ?Sized, S = DefaultScalarValue> {
+    fn resolve_concrete_value_async<'r>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>;
 }
 
 pub trait Field<Info: ?Sized, Ctx: ?Sized, S = DefaultScalarValue> {
     fn resolve_field(
         &self,
-        info: &Info,
         field_name: &str,
         arguments: &Arguments<S>,
+        info: &Info,
         executor: &Executor<Ctx, S>,
     ) -> ExecutionResult<S>;
 }
 
-pub trait ConcreteTypeName<Info: ?Sized> {
-    fn concrete_type_name<'i>(&self, info: &'i Info) -> &'i str;
+pub trait FieldAsync<Info: ?Sized, Ctx: ?Sized, S = DefaultScalarValue> {
+    fn resolve_field_async<'r>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>>;
 }
diff --git a/juniper/src/types/arc.rs b/juniper/src/types/arc.rs
new file mode 100644
index 00000000..8300eec9
--- /dev/null
+++ b/juniper/src/types/arc.rs
@@ -0,0 +1,186 @@
+use std::sync::Arc;
+
+use crate::{
+    executor::{ExecutionResult, Executor, Registry},
+    graphql, resolve,
+    schema::meta::MetaType,
+    Arguments, BoxFuture, Selection,
+};
+
+impl<T, Info, S> resolve::Type<Info, S> for Arc<T>
+where
+    T: resolve::Type<Info, S> + ?Sized,
+    Info: ?Sized,
+{
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+    {
+        T::meta(registry, info)
+    }
+}
+
+impl<T, Info> resolve::TypeName<Info> for Arc<T>
+where
+    T: resolve::TypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn type_name(info: &Info) -> &str {
+        T::type_name(info)
+    }
+}
+
+impl<T, Info> resolve::ConcreteTypeName<Info> for Arc<T>
+where
+    T: resolve::ConcreteTypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn concrete_type_name<'i>(&self, info: &'i Info) -> &'i str {
+        (**self).concrete_type_name(info)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for Arc<T>
+where
+    T: resolve::Value<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_value(selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for Arc<T>
+where
+    T: resolve::ValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_value_async(selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ConcreteValue<Info, Ctx, S> for Arc<T>
+where
+    T: resolve::ConcreteValue<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_concrete_value(type_name, selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ConcreteValueAsync<Info, Ctx, S> for Arc<T>
+where
+    T: resolve::ConcreteValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value_async<'r>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_concrete_value_async(type_name, selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Field<Info, Ctx, S> for Arc<T>
+where
+    T: resolve::Field<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field(
+        &self,
+        field_name: &str,
+        arguments: &Arguments<S>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_field(field_name, arguments, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::FieldAsync<Info, Ctx, S> for Arc<T>
+where
+    T: resolve::FieldAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field_async<'r>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_field_async(field_name, arguments, info, executor)
+    }
+}
+
+impl<T, S> graphql::InputType<S> for Arc<T>
+where
+    T: graphql::InputType<S> + ?Sized,
+{
+    fn assert_input_type() {
+        T::assert_input_type()
+    }
+}
+
+impl<T, S> graphql::OutputType<S> for Arc<T>
+where
+    T: graphql::OutputType<S> + ?Sized,
+{
+    fn assert_output_type() {
+        T::assert_output_type()
+    }
+}
+
+impl<T, S> graphql::Interface<S> for Arc<T>
+where
+    T: graphql::Interface<S> + ?Sized,
+{
+    fn assert_interface() {
+        T::assert_interface()
+    }
+}
+
+impl<T, S> graphql::Object<S> for Arc<T>
+where
+    T: graphql::Object<S> + ?Sized,
+{
+    fn assert_object() {
+        T::assert_object()
+    }
+}
+
+impl<T, S> graphql::Union<S> for Arc<T>
+where
+    T: graphql::Union<S> + ?Sized,
+{
+    fn assert_union() {
+        T::assert_union()
+    }
+}
diff --git a/juniper/src/types/box.rs b/juniper/src/types/box.rs
new file mode 100644
index 00000000..5f0b0ce1
--- /dev/null
+++ b/juniper/src/types/box.rs
@@ -0,0 +1,184 @@
+use crate::{
+    executor::{ExecutionResult, Executor, Registry},
+    graphql, resolve,
+    schema::meta::MetaType,
+    Arguments, BoxFuture, Selection,
+};
+
+impl<T, Info, S> resolve::Type<Info, S> for Box<T>
+where
+    T: resolve::Type<Info, S> + ?Sized,
+    Info: ?Sized,
+{
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+    {
+        T::meta(registry, info)
+    }
+}
+
+impl<T, Info> resolve::TypeName<Info> for Box<T>
+where
+    T: resolve::TypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn type_name(info: &Info) -> &str {
+        T::type_name(info)
+    }
+}
+
+impl<T, Info> resolve::ConcreteTypeName<Info> for Box<T>
+where
+    T: resolve::ConcreteTypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn concrete_type_name<'i>(&self, info: &'i Info) -> &'i str {
+        (**self).concrete_type_name(info)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for Box<T>
+where
+    T: resolve::Value<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_value(selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for Box<T>
+where
+    T: resolve::ValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_value_async(selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ConcreteValue<Info, Ctx, S> for Box<T>
+where
+    T: resolve::ConcreteValue<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_concrete_value(type_name, selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ConcreteValueAsync<Info, Ctx, S> for Box<T>
+where
+    T: resolve::ConcreteValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value_async<'r>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_concrete_value_async(type_name, selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Field<Info, Ctx, S> for Box<T>
+where
+    T: resolve::Field<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field(
+        &self,
+        field_name: &str,
+        arguments: &Arguments<S>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_field(field_name, arguments, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::FieldAsync<Info, Ctx, S> for Box<T>
+where
+    T: resolve::FieldAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field_async<'r>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_field_async(field_name, arguments, info, executor)
+    }
+}
+
+impl<T, S> graphql::InputType<S> for Box<T>
+where
+    T: graphql::InputType<S> + ?Sized,
+{
+    fn assert_input_type() {
+        T::assert_input_type()
+    }
+}
+
+impl<T, S> graphql::OutputType<S> for Box<T>
+where
+    T: graphql::OutputType<S> + ?Sized,
+{
+    fn assert_output_type() {
+        T::assert_output_type()
+    }
+}
+
+impl<T, S> graphql::Interface<S> for Box<T>
+where
+    T: graphql::Interface<S> + ?Sized,
+{
+    fn assert_interface() {
+        T::assert_interface()
+    }
+}
+
+impl<T, S> graphql::Object<S> for Box<T>
+where
+    T: graphql::Object<S> + ?Sized,
+{
+    fn assert_object() {
+        T::assert_object()
+    }
+}
+
+impl<T, S> graphql::Union<S> for Box<T>
+where
+    T: graphql::Union<S> + ?Sized,
+{
+    fn assert_union() {
+        T::assert_union()
+    }
+}
diff --git a/juniper/src/types/iter.rs b/juniper/src/types/iter.rs
new file mode 100644
index 00000000..2b4e5edd
--- /dev/null
+++ b/juniper/src/types/iter.rs
@@ -0,0 +1,65 @@
+use crate::{graphql, resolve, ExecutionResult, Executor, Selection};
+
+pub fn resolve_list<'t, T, S, Info, Ctx, I>(
+    iter: I,
+    selection_set: Option<&[Selection<'_, S>]>,
+    info: &Info,
+    executor: &Executor<Ctx, S>,
+) -> ExecutionResult<S>
+where
+    I: Iterator<Item = &'t T> + ExactSizeIterator,
+    T: resolve::Value<Info, Ctx, S> + ?Sized + 't,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    let is_non_null = executor
+        .current_type_new()
+        .list_contents()
+        .ok_or("Iterating over non-list type")?
+        .is_non_null();
+
+    let mut values = Vec::with_capacity(iter.len());
+    for v in iter {
+        let val = v.resolve_value(selection_set, info, executor)?;
+        if is_non_null && val.is_null() {
+            return Err("Resolved `null` on non-null type".into());
+        }
+        values.push(val);
+    }
+    Ok(graphql::Value::list(values))
+}
+
+pub async fn resolve_list_async<'a, 't, T, S, Info, Ctx, I>(
+    iter: I,
+    selection_set: Option<&[Selection<'_, S>]>,
+    info: &'a Info,
+    executor: &'a Executor<'a, 'a, Ctx, S>,
+) -> ExecutionResult<S>
+where
+    I: Iterator<Item = &'t T> + ExactSizeIterator,
+    T: resolve::ValueAsync<Info, Ctx, S> + ?Sized + 't,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    use futures::stream::{FuturesOrdered, StreamExt as _};
+
+    let is_non_null = executor
+        .current_type_new()
+        .list_contents()
+        .ok_or("Iterating over non-list type")?
+        .is_non_null();
+
+    let mut futs = iter
+        .map(|v| async move { v.resolve_value_async(selection_set, info, executor).await })
+        .collect::<FuturesOrdered<_>>();
+
+    let mut values = Vec::with_capacity(futs.len());
+    while let Some(res) = futs.next().await {
+        let val = res?;
+        if is_non_null && val.is_null() {
+            return Err("Resolved `null` on non-null type".into());
+        }
+        values.push(val);
+    }
+    Ok(graphql::Value::list(values))
+}
diff --git a/juniper/src/types/mod.rs b/juniper/src/types/mod.rs
index 8ac005ba..55451b5a 100644
--- a/juniper/src/types/mod.rs
+++ b/juniper/src/types/mod.rs
@@ -1,3 +1,12 @@
+mod arc;
+mod r#box;
+pub mod iter;
+mod option;
+mod rc;
+mod r#ref;
+mod ref_mut;
+mod vec;
+
 pub mod async_await;
 pub mod base;
 pub mod containers;
diff --git a/juniper/src/types/option.rs b/juniper/src/types/option.rs
new file mode 100644
index 00000000..98f995c4
--- /dev/null
+++ b/juniper/src/types/option.rs
@@ -0,0 +1,78 @@
+use futures::future;
+
+use crate::{
+    executor::{ExecutionResult, Executor, Registry},
+    graphql, resolve,
+    schema::meta::MetaType,
+    BoxFuture, Selection,
+};
+
+impl<T, Info, S> resolve::Type<Info, S> for Option<T>
+where
+    T: resolve::Type<Info, S>,
+    Info: ?Sized,
+{
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+    {
+        registry.build_nullable_type_new::<T, _>(info).into_meta()
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for Option<T>
+where
+    T: resolve::Value<Info, Ctx, S>,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        match self {
+            Some(v) => v.resolve_value(selection_set, info, executor),
+            None => Ok(graphql::Value::Null),
+        }
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for Option<T>
+where
+    T: resolve::ValueAsync<Info, Ctx, S>,
+    Info: ?Sized,
+    Ctx: ?Sized,
+    S: Send,
+{
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        match self {
+            Some(v) => v.resolve_value_async(selection_set, info, executor),
+            None => Box::pin(future::ok(graphql::Value::Null)),
+        }
+    }
+}
+
+impl<T, S> graphql::InputType<S> for Option<T>
+where
+    T: graphql::InputType<S>,
+{
+    fn assert_input_type() {
+        T::assert_input_type()
+    }
+}
+
+impl<T, S> graphql::OutputType<S> for Option<T>
+where
+    T: graphql::OutputType<S>,
+{
+    fn assert_output_type() {
+        T::assert_output_type()
+    }
+}
diff --git a/juniper/src/types/rc.rs b/juniper/src/types/rc.rs
new file mode 100644
index 00000000..0ac2d263
--- /dev/null
+++ b/juniper/src/types/rc.rs
@@ -0,0 +1,186 @@
+use std::rc::Rc;
+
+use crate::{
+    executor::{ExecutionResult, Executor, Registry},
+    graphql, resolve,
+    schema::meta::MetaType,
+    Arguments, BoxFuture, Selection,
+};
+
+impl<T, Info, S> resolve::Type<Info, S> for Rc<T>
+where
+    T: resolve::Type<Info, S> + ?Sized,
+    Info: ?Sized,
+{
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+    {
+        T::meta(registry, info)
+    }
+}
+
+impl<T, Info> resolve::TypeName<Info> for Rc<T>
+where
+    T: resolve::TypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn type_name(info: &Info) -> &str {
+        T::type_name(info)
+    }
+}
+
+impl<T, Info> resolve::ConcreteTypeName<Info> for Rc<T>
+where
+    T: resolve::ConcreteTypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn concrete_type_name<'i>(&self, info: &'i Info) -> &'i str {
+        (**self).concrete_type_name(info)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for Rc<T>
+where
+    T: resolve::Value<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_value(selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for Rc<T>
+where
+    T: resolve::ValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_value_async(selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ConcreteValue<Info, Ctx, S> for Rc<T>
+where
+    T: resolve::ConcreteValue<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_concrete_value(type_name, selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ConcreteValueAsync<Info, Ctx, S> for Rc<T>
+where
+    T: resolve::ConcreteValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value_async<'r>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_concrete_value_async(type_name, selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Field<Info, Ctx, S> for Rc<T>
+where
+    T: resolve::Field<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field(
+        &self,
+        field_name: &str,
+        arguments: &Arguments<S>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_field(field_name, arguments, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::FieldAsync<Info, Ctx, S> for Rc<T>
+where
+    T: resolve::FieldAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field_async<'r>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_field_async(field_name, arguments, info, executor)
+    }
+}
+
+impl<T, S> graphql::InputType<S> for Rc<T>
+where
+    T: graphql::InputType<S> + ?Sized,
+{
+    fn assert_input_type() {
+        T::assert_input_type()
+    }
+}
+
+impl<T, S> graphql::OutputType<S> for Rc<T>
+where
+    T: graphql::OutputType<S> + ?Sized,
+{
+    fn assert_output_type() {
+        T::assert_output_type()
+    }
+}
+
+impl<T, S> graphql::Interface<S> for Rc<T>
+where
+    T: graphql::Interface<S> + ?Sized,
+{
+    fn assert_interface() {
+        T::assert_interface()
+    }
+}
+
+impl<T, S> graphql::Object<S> for Rc<T>
+where
+    T: graphql::Object<S> + ?Sized,
+{
+    fn assert_object() {
+        T::assert_object()
+    }
+}
+
+impl<T, S> graphql::Union<S> for Rc<T>
+where
+    T: graphql::Union<S> + ?Sized,
+{
+    fn assert_union() {
+        T::assert_union()
+    }
+}
diff --git a/juniper/src/types/ref.rs b/juniper/src/types/ref.rs
new file mode 100644
index 00000000..2f086794
--- /dev/null
+++ b/juniper/src/types/ref.rs
@@ -0,0 +1,182 @@
+use crate::{
+    graphql, meta::MetaType, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry,
+    Selection,
+};
+
+impl<'me, T, Info, S> resolve::Type<Info, S> for &'me T
+where
+    T: resolve::Type<Info, S> + ?Sized,
+    Info: ?Sized,
+{
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+    {
+        T::meta(registry, info)
+    }
+}
+
+impl<'me, T, Info> resolve::TypeName<Info> for &'me T
+where
+    T: resolve::TypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn type_name(info: &Info) -> &str {
+        T::type_name(info)
+    }
+}
+
+impl<'me, T, Info> resolve::ConcreteTypeName<Info> for &'me T
+where
+    T: resolve::ConcreteTypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn concrete_type_name<'i>(&self, info: &'i Info) -> &'i str {
+        (**self).concrete_type_name(info)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for &'me T
+where
+    T: resolve::Value<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_value(selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for &'me T
+where
+    T: resolve::ValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_value_async(selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::ConcreteValue<Info, Ctx, S> for &'me T
+where
+    T: resolve::ConcreteValue<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_concrete_value(type_name, selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::ConcreteValueAsync<Info, Ctx, S> for &'me T
+where
+    T: resolve::ConcreteValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value_async<'r>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_concrete_value_async(type_name, selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::Field<Info, Ctx, S> for &'me T
+where
+    T: resolve::Field<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field(
+        &self,
+        field_name: &str,
+        arguments: &Arguments<S>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_field(field_name, arguments, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::FieldAsync<Info, Ctx, S> for &'me T
+where
+    T: resolve::FieldAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field_async<'r>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_field_async(field_name, arguments, info, executor)
+    }
+}
+
+impl<'me, T, S> graphql::InputType<S> for &'me T
+where
+    T: graphql::InputType<S> + ?Sized,
+{
+    fn assert_input_type() {
+        T::assert_input_type()
+    }
+}
+
+impl<'me, T, S> graphql::OutputType<S> for &'me T
+where
+    T: graphql::OutputType<S> + ?Sized,
+{
+    fn assert_output_type() {
+        T::assert_output_type()
+    }
+}
+
+impl<'me, T, S> graphql::Interface<S> for &'me T
+where
+    T: graphql::Interface<S> + ?Sized,
+{
+    fn assert_interface() {
+        T::assert_interface()
+    }
+}
+
+impl<'me, T, S> graphql::Object<S> for &'me T
+where
+    T: graphql::Object<S> + ?Sized,
+{
+    fn assert_object() {
+        T::assert_object()
+    }
+}
+
+impl<'me, T, S> graphql::Union<S> for &'me T
+where
+    T: graphql::Union<S> + ?Sized,
+{
+    fn assert_union() {
+        T::assert_union()
+    }
+}
diff --git a/juniper/src/types/ref_mut.rs b/juniper/src/types/ref_mut.rs
new file mode 100644
index 00000000..566359b6
--- /dev/null
+++ b/juniper/src/types/ref_mut.rs
@@ -0,0 +1,182 @@
+use crate::{
+    graphql, meta::MetaType, resolve, Arguments, BoxFuture, ExecutionResult, Executor, Registry,
+    Selection,
+};
+
+impl<'me, T, Info, S> resolve::Type<Info, S> for &'me mut T
+where
+    T: resolve::Type<Info, S> + ?Sized,
+    Info: ?Sized,
+{
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+    {
+        T::meta(registry, info)
+    }
+}
+
+impl<'me, T, Info> resolve::TypeName<Info> for &'me mut T
+where
+    T: resolve::TypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn type_name(info: &Info) -> &str {
+        T::type_name(info)
+    }
+}
+
+impl<'me, T, Info> resolve::ConcreteTypeName<Info> for &'me mut T
+where
+    T: resolve::ConcreteTypeName<Info> + ?Sized,
+    Info: ?Sized,
+{
+    fn concrete_type_name<'i>(&self, info: &'i Info) -> &'i str {
+        (**self).concrete_type_name(info)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for &'me mut T
+where
+    T: resolve::Value<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_value(selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for &'me mut T
+where
+    T: resolve::ValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_value_async(selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::ConcreteValue<Info, Ctx, S> for &'me mut T
+where
+    T: resolve::ConcreteValue<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value(
+        &self,
+        type_name: &str,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_concrete_value(type_name, selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::ConcreteValueAsync<Info, Ctx, S> for &'me mut T
+where
+    T: resolve::ConcreteValueAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_concrete_value_async<'r>(
+        &'r self,
+        type_name: &str,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_concrete_value_async(type_name, selection_set, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::Field<Info, Ctx, S> for &'me mut T
+where
+    T: resolve::Field<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field(
+        &self,
+        field_name: &str,
+        arguments: &Arguments<S>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        (**self).resolve_field(field_name, arguments, info, executor)
+    }
+}
+
+impl<'me, T, Info, Ctx, S> resolve::FieldAsync<Info, Ctx, S> for &'me mut T
+where
+    T: resolve::FieldAsync<Info, Ctx, S> + ?Sized,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_field_async<'r>(
+        &'r self,
+        field_name: &'r str,
+        arguments: &'r Arguments<S>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        (**self).resolve_field_async(field_name, arguments, info, executor)
+    }
+}
+
+impl<'me, T, S> graphql::InputType<S> for &'me mut T
+where
+    T: graphql::InputType<S> + ?Sized,
+{
+    fn assert_input_type() {
+        T::assert_input_type()
+    }
+}
+
+impl<'me, T, S> graphql::OutputType<S> for &'me mut T
+where
+    T: graphql::OutputType<S> + ?Sized,
+{
+    fn assert_output_type() {
+        T::assert_output_type()
+    }
+}
+
+impl<'me, T, S> graphql::Interface<S> for &'me mut T
+where
+    T: graphql::Interface<S> + ?Sized,
+{
+    fn assert_interface() {
+        T::assert_interface()
+    }
+}
+
+impl<'me, T, S> graphql::Object<S> for &'me mut T
+where
+    T: graphql::Object<S> + ?Sized,
+{
+    fn assert_object() {
+        T::assert_object()
+    }
+}
+
+impl<'me, T, S> graphql::Union<S> for &'me mut T
+where
+    T: graphql::Union<S> + ?Sized,
+{
+    fn assert_union() {
+        T::assert_union()
+    }
+}
diff --git a/juniper/src/types/vec.rs b/juniper/src/types/vec.rs
new file mode 100644
index 00000000..e2374e27
--- /dev/null
+++ b/juniper/src/types/vec.rs
@@ -0,0 +1,77 @@
+use crate::{
+    executor::{ExecutionResult, Executor, Registry},
+    graphql, resolve,
+    schema::meta::MetaType,
+    BoxFuture, Selection,
+};
+
+use super::iter;
+
+impl<T, Info, S> resolve::Type<Info, S> for Vec<T>
+where
+    T: resolve::Type<Info, S>,
+    Info: ?Sized,
+{
+    fn meta<'r>(registry: &mut Registry<'r, S>, info: &Info) -> MetaType<'r, S>
+    where
+        S: 'r,
+    {
+        registry.build_list_type_new::<T, _>(info, None).into_meta()
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::Value<Info, Ctx, S> for Vec<T>
+where
+    T: resolve::Value<Info, Ctx, S>,
+    Info: ?Sized,
+    Ctx: ?Sized,
+{
+    fn resolve_value(
+        &self,
+        selection_set: Option<&[Selection<'_, S>]>,
+        info: &Info,
+        executor: &Executor<Ctx, S>,
+    ) -> ExecutionResult<S> {
+        iter::resolve_list(self.iter(), selection_set, info, executor)
+    }
+}
+
+impl<T, Info, Ctx, S> resolve::ValueAsync<Info, Ctx, S> for Vec<T>
+where
+    T: resolve::ValueAsync<Info, Ctx, S> + Sync,
+    Info: Sync + ?Sized,
+    Ctx: Sync + ?Sized,
+    S: Send + Sync,
+{
+    fn resolve_value_async<'r>(
+        &'r self,
+        selection_set: Option<&'r [Selection<'_, S>]>,
+        info: &'r Info,
+        executor: &'r Executor<Ctx, S>,
+    ) -> BoxFuture<'r, ExecutionResult<S>> {
+        Box::pin(iter::resolve_list_async(
+            self.iter(),
+            selection_set,
+            info,
+            executor,
+        ))
+    }
+}
+
+impl<T, S> graphql::InputType<S> for Vec<T>
+where
+    T: graphql::InputType<S>,
+{
+    fn assert_input_type() {
+        T::assert_input_type()
+    }
+}
+
+impl<T, S> graphql::OutputType<S> for Vec<T>
+where
+    T: graphql::OutputType<S>,
+{
+    fn assert_output_type() {
+        T::assert_output_type()
+    }
+}