From 5a62ddfbf224b6a0ee3711e2b42a15b887e7f5e7 Mon Sep 17 00:00:00 2001
From: tyranron <tyranron@gmail.com>
Date: Wed, 8 Jun 2022 11:06:28 +0200
Subject: [PATCH] Restore old reflection impls

---
 juniper/src/macros/reflect.rs             | 122 +++++++++++++++++++++-
 juniper/src/types/nullable.rs             |   6 +-
 juniper/src/types/scalars.rs              |  13 +++
 juniper_codegen/src/graphql_scalar/mod.rs |  59 +++++++++--
 4 files changed, 187 insertions(+), 13 deletions(-)

diff --git a/juniper/src/macros/reflect.rs b/juniper/src/macros/reflect.rs
index b24ba4f5..e67762df 100644
--- a/juniper/src/macros/reflect.rs
+++ b/juniper/src/macros/reflect.rs
@@ -7,7 +7,7 @@ use crate::{
         can_be_subtype, fnv1a128, str_eq, str_exists_in_arr, type_len_with_wrapped_val, wrap,
         Argument, Arguments, FieldName, Name, Names, Type, Types, WrappedValue,
     },
-    Arguments as FieldArguments, ExecutionResult, Executor, GraphQLValue, ScalarValue,
+    Arguments as FieldArguments, ExecutionResult, Executor, GraphQLValue, ScalarValue, Nullable,
 };
 
 /// Naming of a [GraphQL object][1], [scalar][2] or [interface][3] [`Type`].
@@ -31,6 +31,10 @@ pub trait BaseType<S> {
     const NAME: Type;
 }
 
+impl<'a, S, T: BaseType<S> + ?Sized> BaseType<S> for &'a T {
+    const NAME: Type = T::NAME;
+}
+
 impl<'ctx, S, T> BaseType<S> for (&'ctx T::Context, T)
 where
     S: ScalarValue,
@@ -39,6 +43,42 @@ where
     const NAME: Type = T::NAME;
 }
 
+impl<S, T: BaseType<S>> BaseType<S> for Option<T> {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S>> BaseType<S> for Nullable<T> {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S>, E> BaseType<S> for Result<T, E> {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S>> BaseType<S> for Vec<T> {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S>> BaseType<S> for [T] {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S>, const N: usize> BaseType<S> for [T; N] {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S> + ?Sized> BaseType<S> for Box<T> {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S> + ?Sized> BaseType<S> for Arc<T> {
+    const NAME: Type = T::NAME;
+}
+
+impl<S, T: BaseType<S> + ?Sized> BaseType<S> for Rc<T> {
+    const NAME: Type = T::NAME;
+}
+
 /// [Sub-types][2] of a [GraphQL object][1].
 ///
 /// This trait is transparent to [`Option`], [`Vec`] and other containers.
@@ -52,6 +92,10 @@ pub trait BaseSubTypes<S> {
     const NAMES: Types;
 }
 
+impl<'a, S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for &'a T {
+    const NAMES: Types = T::NAMES;
+}
+
 impl<'ctx, S, T> BaseSubTypes<S> for (&'ctx T::Context, T)
 where
     S: ScalarValue,
@@ -60,6 +104,42 @@ where
     const NAMES: Types = T::NAMES;
 }
 
+impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for Option<T> {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for Nullable<T> {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S>, E> BaseSubTypes<S> for Result<T, E> {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for Vec<T> {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S>> BaseSubTypes<S> for [T] {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S>, const N: usize> BaseSubTypes<S> for [T; N] {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for Box<T> {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for Arc<T> {
+    const NAMES: Types = T::NAMES;
+}
+
+impl<S, T: BaseSubTypes<S> + ?Sized> BaseSubTypes<S> for Rc<T> {
+    const NAMES: Types = T::NAMES;
+}
+
 // TODO: Just use `&str`s once they're allowed in `const` generics.
 /// Encoding of a composed GraphQL type in numbers.
 ///
@@ -117,6 +197,46 @@ where
     const VALUE: u128 = T::VALUE;
 }
 
+impl<S, T: WrappedType<S>> WrappedType<S> for Option<T> {
+    const VALUE: u128 = T::VALUE * 10 + 2;
+}
+
+impl<S, T: WrappedType<S>> WrappedType<S> for Nullable<T> {
+    const VALUE: u128 = T::VALUE * 10 + 2;
+}
+
+impl<S, T: WrappedType<S>, E> WrappedType<S> for Result<T, E> {
+    const VALUE: u128 = T::VALUE;
+}
+
+impl<S, T: WrappedType<S>> WrappedType<S> for Vec<T> {
+    const VALUE: u128 = T::VALUE * 10 + 3;
+}
+
+impl<S, T: WrappedType<S>> WrappedType<S> for [T] {
+    const VALUE: u128 = T::VALUE * 10 + 3;
+}
+
+impl<S, T: WrappedType<S>, const N: usize> WrappedType<S> for [T; N] {
+    const VALUE: u128 = T::VALUE * 10 + 3;
+}
+
+impl<'a, S, T: WrappedType<S> + ?Sized> WrappedType<S> for &'a T {
+    const VALUE: u128 = T::VALUE;
+}
+
+impl<S, T: WrappedType<S> + ?Sized> WrappedType<S> for Box<T> {
+    const VALUE: u128 = T::VALUE;
+}
+
+impl<S, T: WrappedType<S> + ?Sized> WrappedType<S> for Arc<T> {
+    const VALUE: u128 = T::VALUE;
+}
+
+impl<S, T: WrappedType<S> + ?Sized> WrappedType<S> for Rc<T> {
+    const VALUE: u128 = T::VALUE;
+}
+
 /// [GraphQL object][1] or [interface][2] [field arguments][3] [`Names`].
 ///
 /// [1]: https://spec.graphql.org/October2021#sec-Objects
diff --git a/juniper/src/types/nullable.rs b/juniper/src/types/nullable.rs
index 04165f3b..daec6044 100644
--- a/juniper/src/types/nullable.rs
+++ b/juniper/src/types/nullable.rs
@@ -244,7 +244,7 @@ impl<T: Copy> Nullable<&T> {
     /// Maps this `Nullable<&T>` to a `Nullable<T>` by [`Copy`]ing the contents
     /// of this [`Nullable`].
     pub fn copied(self) -> Nullable<T> {
-        self.map(|&t| t)
+        self.map(|t| *t)
     }
 }
 
@@ -252,7 +252,7 @@ impl<T: Copy> Nullable<&mut T> {
     /// Maps this `Nullable<&mut T>` to a `Nullable<T>` by [`Copy`]ing the
     /// contents of this [`Nullable`].
     pub fn copied(self) -> Nullable<T> {
-        self.map(|&mut t| t)
+        self.map(|t| *t)
     }
 }
 
@@ -260,7 +260,7 @@ impl<T: Clone> Nullable<&T> {
     /// Maps this `Nullable<&T>` to a `Nullable<T>` by [`Clone`]ing the contents
     /// of this [`Nullable`].
     pub fn cloned(self) -> Nullable<T> {
-        self.map(|t| t.clone())
+        self.map(T::clone)
     }
 }
 
diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs
index 0f8bb408..66e26e74 100644
--- a/juniper/src/types/scalars.rs
+++ b/juniper/src/types/scalars.rs
@@ -8,6 +8,7 @@ use crate::{
     ast::{InputValue, Selection, ToInputValue},
     executor::{ExecutionResult, Executor, Registry},
     graphql_scalar,
+    macros::reflect,
     parser::{LexerError, ParseError, ScalarToken, Token},
     schema::meta::MetaType,
     types::{
@@ -195,6 +196,18 @@ where
     })
 }
 
+impl<S> reflect::WrappedType<S> for str {
+    const VALUE: reflect::WrappedValue = 1;
+}
+
+impl<S> reflect::BaseType<S> for str {
+    const NAME: reflect::Type = "String";
+}
+
+impl<S> reflect::BaseSubTypes<S> for str {
+    const NAMES: reflect::Types = &[<Self as reflect::BaseType<S>>::NAME];
+}
+
 impl<S> GraphQLType<S> for str
 where
     S: ScalarValue,
diff --git a/juniper_codegen/src/graphql_scalar/mod.rs b/juniper_codegen/src/graphql_scalar/mod.rs
index 9e6e49cf..5a706851 100644
--- a/juniper_codegen/src/graphql_scalar/mod.rs
+++ b/juniper_codegen/src/graphql_scalar/mod.rs
@@ -329,17 +329,19 @@ impl ToTokens for Definition {
         self.impl_to_input_value_tokens().to_tokens(into);
         self.impl_from_input_value_tokens().to_tokens(into);
         self.impl_parse_scalar_value_tokens().to_tokens(into);
+        self.impl_reflection_traits_tokens().to_tokens(into);
         ////////////////////////////////////////////////////////////////////////
-        self.impl_resolve_type().to_tokens(into);
-        self.impl_resolve_type_name().to_tokens(into);
-        self.impl_resolve_value().to_tokens(into);
-        self.impl_resolve_value_async().to_tokens(into);
-        self.impl_resolve_to_input_value().to_tokens(into);
-        self.impl_resolve_input_value().to_tokens(into);
-        self.impl_resolve_scalar_token().to_tokens(into);
-        //self.impl_graphql_input_and_output_type().to_tokens(into);
+        //self.impl_resolve_type().to_tokens(into);
+        //self.impl_resolve_type_name().to_tokens(into);
+        //self.impl_resolve_value().to_tokens(into);
+        //self.impl_resolve_value_async().to_tokens(into);
+        //self.impl_resolve_to_input_value().to_tokens(into);
+        //self.impl_resolve_input_value().to_tokens(into);
+        //self.impl_resolve_scalar_token().to_tokens(into);
+        //self.impl_graphql_output_type().to_tokens(into);
+        //self.impl_graphql_output_type().to_tokens(into);
         //self.impl_graphql_scalar().to_tokens(into);
-        self.impl_reflect().to_tokens(into);
+        //self.impl_reflect().to_tokens(into);
     }
 }
 
@@ -850,6 +852,45 @@ impl Definition {
         }
     }
 
+    /// Returns generated code implementing [`BaseType`], [`BaseSubTypes`] and
+    /// [`WrappedType`] traits for this [GraphQL scalar][1].
+    ///
+    /// [`BaseSubTypes`]: juniper::macros::reflection::BaseSubTypes
+    /// [`BaseType`]: juniper::macros::reflection::BaseType
+    /// [`WrappedType`]: juniper::macros::reflection::WrappedType
+    /// [1]: https://spec.graphql.org/October2021#sec-Scalars
+    fn impl_reflection_traits_tokens(&self) -> TokenStream {
+        let scalar = &self.scalar;
+        let name = &self.name;
+
+        let (ty, generics) = self.impl_self_and_generics(false);
+        let (impl_gens, _, where_clause) = generics.split_for_impl();
+
+        quote! {
+            #[automatically_derived]
+            impl#impl_gens ::juniper::macros::reflect::BaseType<#scalar> for #ty
+                #where_clause
+            {
+                const NAME: ::juniper::macros::reflect::Type = #name;
+            }
+
+            #[automatically_derived]
+            impl#impl_gens ::juniper::macros::reflect::BaseSubTypes<#scalar> for #ty
+                #where_clause
+            {
+                const NAMES: ::juniper::macros::reflect::Types =
+                    &[<Self as ::juniper::macros::reflect::BaseType<#scalar>>::NAME];
+            }
+
+            #[automatically_derived]
+            impl#impl_gens ::juniper::macros::reflect::WrappedType<#scalar> for #ty
+                #where_clause
+            {
+                const VALUE: ::juniper::macros::reflect::WrappedValue = 1;
+            }
+        }
+    }
+
     /// Returns generated code implementing [`reflect::BaseType`],
     /// [`reflect::BaseSubTypes`] and [`reflect::WrappedType`] traits for this
     /// [GraphQL scalar][0].