Repository: graphql-rust/juniper (language: rust)

Issue:
Panic when using look ahead together nullable variables
**Describe the bug**
If you have a query with a nullable variable, and the resolver calls `executor.look_ahead()` then you get a panic if you don't set the variable at all. However if you set the variable to `null` it doesn't panic 🤔 

**To Reproduce**
Steps to reproduce the behavior: Download https://github.com/davidpdrsn/juniper-variable-bug and run `cargo test`.


**Expected behavior**
I imagine these two scenarios should behave identically. I would expect neither of them to panic or error.


**Additional context**
I discovered this because the code generated by [juniper-from-schema](https://github.com/davidpdrsn/juniper-from-schema) calls `.look_ahead()` for all fields.


Discussion / hints:

Fix patch:
diff --git a/juniper/src/executor/look_ahead.rs b/juniper/src/executor/look_ahead.rs
index ec6ce6b71..1c3e27e44 100644
--- a/juniper/src/executor/look_ahead.rs
+++ b/juniper/src/executor/look_ahead.rs
@@ -39,7 +39,13 @@ where
             InputValue::Null => LookAheadValue::Null,
             InputValue::Scalar(ref s) => LookAheadValue::Scalar(s),
             InputValue::Enum(ref e) => LookAheadValue::Enum(e),
-            InputValue::Variable(ref v) => Self::from_input_value(vars.get(v).unwrap(), vars),
+            InputValue::Variable(ref name) => {
+                let value = vars
+                    .get(name)
+                    .map(|v| Self::from_input_value(v, vars))
+                    .unwrap_or(LookAheadValue::Null);
+                value
+            }
             InputValue::List(ref l) => LookAheadValue::List(
                 l.iter()
                     .map(|i| LookAheadValue::from_input_value(&i.item, vars))
@@ -720,6 +726,50 @@ query Hero($episode: Episode) {
         }
     }
 
+    #[test]
+    fn check_query_with_optional_variable() {
+        let docs = parse_document_source::<DefaultScalarValue>(
+            "
+query Hero($episode: Episode) {
+    hero(episode: $episode) {
+        id
+    }
+}
+",
+        )
+        .unwrap();
+        let fragments = extract_fragments(&docs);
+
+        if let crate::ast::Definition::Operation(ref op) = docs[0] {
+            let vars = Variables::default();
+            let look_ahead = LookAheadSelection::build_from_selection(
+                &op.item.selection_set[0],
+                &vars,
+                &fragments,
+            )
+            .unwrap();
+            let expected = LookAheadSelection {
+                name: "hero",
+                alias: None,
+                arguments: vec![LookAheadArgument {
+                    name: "episode",
+                    value: LookAheadValue::Null,
+                }],
+                children: vec![ChildSelection {
+                    inner: LookAheadSelection {
+                        name: "id",
+                        alias: None,
+                        arguments: Vec::new(),
+                        children: Vec::new(),
+                    },
+                    applies_for: Applies::All,
+                }],
+            };
+            assert_eq!(look_ahead, expected);
+        } else {
+            panic!("No Operation found");
+        }
+    }
     #[test]
     fn check_query_with_fragment() {
         let docs = parse_document_source::<DefaultScalarValue>(


Test patch: