From 779208eea550291f3d37e902ed89c124526d9f77 Mon Sep 17 00:00:00 2001
From: Andrey Kutejko <andy128k@gmail.com>
Date: Thu, 24 Oct 2019 03:04:48 +0200
Subject: [PATCH] Bubble up scalar error (#434)

---
 juniper/src/parser/parser.rs         |  4 ++++
 juniper/src/parser/tests/document.rs | 21 +++++++++++++++++++
 juniper/src/parser/value.rs          | 31 +++++++++++++++-------------
 3 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/juniper/src/parser/parser.rs b/juniper/src/parser/parser.rs
index e010180d..095fc1e7 100644
--- a/juniper/src/parser/parser.rs
+++ b/juniper/src/parser/parser.rs
@@ -13,6 +13,9 @@ pub enum ParseError<'a> {
 
     /// An error during tokenization occurred
     LexerError(LexerError),
+
+    /// A scalar of unexpected type occurred in the source
+    ExpectedScalarError(&'static str),
 }
 
 #[doc(hidden)]
@@ -196,6 +199,7 @@ impl<'a> fmt::Display for ParseError<'a> {
             ParseError::UnexpectedToken(ref token) => write!(f, "Unexpected \"{}\"", token),
             ParseError::UnexpectedEndOfFile => write!(f, "Unexpected end of input"),
             ParseError::LexerError(ref err) => err.fmt(f),
+            ParseError::ExpectedScalarError(err) => err.fmt(f),
         }
     }
 }
diff --git a/juniper/src/parser/tests/document.rs b/juniper/src/parser/tests/document.rs
index 97b6c31d..cfe18d64 100644
--- a/juniper/src/parser/tests/document.rs
+++ b/juniper/src/parser/tests/document.rs
@@ -4,6 +4,7 @@ use crate::{
     },
     parser::{document::parse_document_source, ParseError, SourcePosition, Spanning, Token},
     schema::model::SchemaType,
+    types::scalars::EmptyMutation,
     validation::test_harness::{MutationRoot, QueryRoot},
     value::{DefaultScalarValue, ScalarRefValue, ScalarValue},
 };
@@ -145,3 +146,23 @@ fn errors() {
         )
     );
 }
+
+#[test]
+fn issue_427_panic_is_not_expected() {
+    struct QueryWithoutFloat;
+
+    #[crate::object_internal]
+    impl QueryWithoutFloat {
+        fn echo(value: String) -> String {
+            value
+        }
+    }
+
+    let schema = SchemaType::new::<QueryWithoutFloat, EmptyMutation<()>>(&(), &());
+    let parse_result = parse_document_source(r##"{ echo(value: 123.0) }"##, &schema);
+
+    assert_eq!(
+        parse_result.unwrap_err().item,
+        ParseError::ExpectedScalarError("There needs to be a Float type")
+    );
+}
diff --git a/juniper/src/parser/value.rs b/juniper/src/parser/value.rs
index 74dde9f9..260f9ec0 100644
--- a/juniper/src/parser/value.rs
+++ b/juniper/src/parser/value.rs
@@ -210,33 +210,36 @@ fn parse_scalar_literal_by_infered_type<'a, 'b, S>(
 where
     S: ScalarValue,
 {
-    match token {
+    let result = match token {
         ScalarToken::String(_) => {
             if let Some(&MetaType::Scalar(ref s)) = schema.concrete_type_by_name("String") {
-                (s.parse_fn)(token)
-                    .map(|s| Spanning::start_end(start, end, InputValue::Scalar(s)))
-                    .map_err(|e| Spanning::start_end(start, end, e))
+                (s.parse_fn)(token).map(InputValue::Scalar)
             } else {
-                panic!("There needs to be a String type")
+                Err(ParseError::ExpectedScalarError(
+                    "There needs to be a String type",
+                ))
             }
         }
         ScalarToken::Int(_) => {
             if let Some(&MetaType::Scalar(ref s)) = schema.concrete_type_by_name("Int") {
-                (s.parse_fn)(token)
-                    .map(|s| Spanning::start_end(start, end, InputValue::Scalar(s)))
-                    .map_err(|e| Spanning::start_end(start, end, e))
+                (s.parse_fn)(token).map(InputValue::Scalar)
             } else {
-                panic!("There needs to be a Int type")
+                Err(ParseError::ExpectedScalarError(
+                    "There needs to be an Int type",
+                ))
             }
         }
         ScalarToken::Float(_) => {
             if let Some(&MetaType::Scalar(ref s)) = schema.concrete_type_by_name("Float") {
-                (s.parse_fn)(token)
-                    .map(|s| Spanning::start_end(start, end, InputValue::Scalar(s)))
-                    .map_err(|e| Spanning::start_end(start, end, e))
+                (s.parse_fn)(token).map(InputValue::Scalar)
             } else {
-                panic!("There needs to be a Float type")
+                Err(ParseError::ExpectedScalarError(
+                    "There needs to be a Float type",
+                ))
             }
         }
-    }
+    };
+    result
+        .map(|s| Spanning::start_end(start, end, s))
+        .map_err(|e| Spanning::start_end(start, end, e))
 }