Attach location info to errors
diff --git a/third_party/Cargo.toml b/third_party/Cargo.toml
index b0cd7c5..e1577d8 100644
--- a/third_party/Cargo.toml
+++ b/third_party/Cargo.toml
@@ -15,5 +15,6 @@
 serde = "1.0"
 
 [dev-dependencies]
+matches = "0.1.8"
 serde_derive = "1.0"
 serde_json = "1.0"
diff --git a/third_party/src/de.rs b/third_party/src/de.rs
index 8596f3a..bfe06ec 100644
--- a/third_party/src/de.rs
+++ b/third_party/src/de.rs
@@ -7,7 +7,7 @@
 use std::collections::VecDeque;
 use std::f64;
 
-use crate::error::{Error, Result};
+use crate::error::{self, Error, Result};
 
 #[derive(Parser)]
 #[grammar = "json5.pest"]
@@ -48,21 +48,26 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        match pair.as_rule() {
-            Rule::null => visitor.visit_unit(),
-            Rule::boolean => visitor.visit_bool(parse_bool(&pair)),
-            Rule::string | Rule::identifier => visitor.visit_string(parse_string(pair)?),
-            Rule::number => {
-                if is_int(pair.as_str()) {
-                    visitor.visit_i64(parse_integer(&pair)?)
-                } else {
-                    visitor.visit_f64(parse_number(&pair)?)
+        let span = pair.as_span();
+        let mut res = (move || {
+            match pair.as_rule() {
+                Rule::null => visitor.visit_unit(),
+                Rule::boolean => visitor.visit_bool(parse_bool(&pair)),
+                Rule::string | Rule::identifier => visitor.visit_string(parse_string(pair)?),
+                Rule::number => {
+                    if is_int(pair.as_str()) {
+                        visitor.visit_i64(parse_integer(&pair)?)
+                    } else {
+                        visitor.visit_f64(parse_number(&pair)?)
+                    }
                 }
+                Rule::array => visitor.visit_seq(Seq::new(pair)),
+                Rule::object => visitor.visit_map(Map::new(pair)),
+                _ => unreachable!(),
             }
-            Rule::array => visitor.visit_seq(Seq::new(pair)),
-            Rule::object => visitor.visit_map(Map::new(pair)),
-            _ => unreachable!(),
-        }
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_enum<V>(
@@ -74,9 +79,13 @@
     where
         V: de::Visitor<'de>,
     {
-        visitor.visit_enum(Enum {
-            pair: self.pair.take().unwrap(),
-        })
+        let pair = self.pair.take().unwrap();
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_enum(Enum { pair })
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     // The below will get us the right types, but won't necessarily give
@@ -86,7 +95,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_i8(parse_number(&pair)? as i8)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_i8(parse_number(&pair)? as i8)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
@@ -94,7 +108,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_i16(parse_number(&pair)? as i16)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_i16(parse_number(&pair)? as i16)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
@@ -102,7 +121,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_i32(parse_number(&pair)? as i32)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_i32(parse_number(&pair)? as i32)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
@@ -110,7 +134,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_i64(parse_number(&pair)? as i64)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_i64(parse_number(&pair)? as i64)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value>
@@ -118,7 +147,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_i128(parse_number(&pair)? as i128)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_i128(parse_number(&pair)? as i128)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
@@ -126,7 +160,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_u8(parse_number(&pair)? as u8)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_u8(parse_number(&pair)? as u8)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
@@ -134,7 +173,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_u16(parse_number(&pair)? as u16)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_u16(parse_number(&pair)? as u16)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
@@ -142,7 +186,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_u32(parse_number(&pair)? as u32)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_u32(parse_number(&pair)? as u32)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
@@ -150,7 +199,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_u64(parse_number(&pair)? as u64)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_u64(parse_number(&pair)? as u64)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value>
@@ -158,7 +212,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_u128(parse_number(&pair)? as u128)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_u128(parse_number(&pair)? as u128)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
@@ -166,7 +225,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_f32(parse_number(&pair)? as f32)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_f32(parse_number(&pair)? as f32)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
@@ -174,7 +238,12 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        visitor.visit_f64(parse_number(&pair)?)
+        let span = pair.as_span();
+        let mut res = (move || {
+            visitor.visit_f64(parse_number(&pair)?)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
@@ -182,17 +251,27 @@
         V: de::Visitor<'de>,
     {
         let pair = self.pair.take().unwrap();
-        match pair.as_rule() {
-            Rule::null => visitor.visit_none(),
-            _ => visitor.visit_some(&mut Deserializer::from_pair(pair)),
-        }
+        let span = pair.as_span();
+        let mut res = (move || {
+            match pair.as_rule() {
+                Rule::null => visitor.visit_none(),
+                _ => visitor.visit_some(&mut Deserializer::from_pair(pair)),
+            }
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
     where
         V: de::Visitor<'de>,
     {
-        visitor.visit_newtype_struct(self)
+        let span = self.pair.as_ref().unwrap().as_span();
+        let mut res = (move || {
+            visitor.visit_newtype_struct(self)
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 
     forward_to_deserialize_any! {
@@ -210,6 +289,8 @@
 }
 
 fn parse_string(pair: Pair<'_, Rule>) -> Result<String> {
+    let span = pair.as_span();
+    let mut res = (move || {
     pair.into_inner()
         .map(|component| match component.as_rule() {
             Rule::char_literal => Ok(String::from(component.as_str())),
@@ -225,6 +306,9 @@
             _ => unreachable!(),
         })
         .collect()
+    })();
+    error::set_location(&mut res, &span);
+    res
 }
 
 fn parse_char_escape_sequence(pair: &Pair<'_, Rule>) -> String {
@@ -365,23 +449,28 @@
     where
         V: de::DeserializeSeed<'de>,
     {
-        match self.pair.as_rule() {
-            Rule::string => {
-                let tag = seed.deserialize(&mut Deserializer::from_pair(self.pair))?;
-                Ok((tag, Variant { pair: None }))
-            }
-            Rule::object => {
-                let mut pairs = self.pair.into_inner();
-
-                if let Some(tag_pair) = pairs.next() {
-                    let tag = seed.deserialize(&mut Deserializer::from_pair(tag_pair))?;
-                    Ok((tag, Variant { pair: pairs.next() }))
-                } else {
-                    Err(de::Error::custom("expected a nonempty object"))
+        let span = self.pair.as_span();
+        let mut res = (move || {
+            match self.pair.as_rule() {
+                Rule::string => {
+                    let tag = seed.deserialize(&mut Deserializer::from_pair(self.pair))?;
+                    Ok((tag, Variant { pair: None }))
                 }
+                Rule::object => {
+                    let mut pairs = self.pair.into_inner();
+
+                    if let Some(tag_pair) = pairs.next() {
+                        let tag = seed.deserialize(&mut Deserializer::from_pair(tag_pair))?;
+                        Ok((tag, Variant { pair: pairs.next() }))
+                    } else {
+                        Err(de::Error::custom("expected a nonempty object"))
+                    }
+                }
+                _ => Err(de::Error::custom("expected a string or an object")),
             }
-            _ => Err(de::Error::custom("expected a string or an object")),
-        }
+        })();
+        error::set_location(&mut res, &span);
+        res
     }
 }
 
diff --git a/third_party/src/error.rs b/third_party/src/error.rs
index 4399ea0..4da921c 100644
--- a/third_party/src/error.rs
+++ b/third_party/src/error.rs
@@ -1,3 +1,4 @@
+use pest::Span;
 use serde::{de, ser};
 use std::fmt::{self, Display};
 
@@ -6,43 +7,75 @@
 /// Alias for a `Result` with error type `json5::Error`
 pub type Result<T> = std::result::Result<T, Error>;
 
+/// One-based line and column at which the error was detected.
+#[derive(Clone, Debug, PartialEq)]
+pub struct Location {
+    /// The one-based line number of the error.
+    pub line: usize,
+    /// The one-based column number of the error.
+    pub column: usize,
+}
+
+impl From<&Span<'_>> for Location {
+    fn from(s: &Span<'_>) -> Self {
+        let (line, column) = s.start_pos().line_col();
+        Self { line, column }
+    }
+}
+
 /// A bare bones error type which currently just collapses all the underlying errors in to a single
 /// string... This is fine for displaying to the user, but not very useful otherwise. Work to be
 /// done here.
 #[derive(Clone, Debug, PartialEq)]
 pub enum Error {
     /// Just shove everything in a single variant for now.
-    Message(String),
+    Message {
+        /// The error message.
+        msg: String,
+        /// The location of the error, if applicable.
+        location: Option<Location>
+    },
 }
 
 impl From<pest::error::Error<Rule>> for Error {
     fn from(err: pest::error::Error<Rule>) -> Self {
-        Error::Message(err.to_string())
+        let (line, column) = match err.line_col {
+            pest::error::LineColLocation::Pos((l, c)) => (l, c),
+            pest::error::LineColLocation::Span((l, c), (_, _)) => (l, c),
+        };
+        Error::Message { msg: err.to_string(), location: Some(Location { line, column }) }
     }
 }
 
 impl ser::Error for Error {
     fn custom<T: Display>(msg: T) -> Self {
-        Error::Message(msg.to_string())
+        Error::Message { msg: msg.to_string(), location: None }
     }
 }
 
 impl de::Error for Error {
     fn custom<T: Display>(msg: T) -> Self {
-        Error::Message(msg.to_string())
+        Error::Message { msg: msg.to_string(), location: None }
     }
 }
 
 impl Display for Error {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        formatter.write_str(std::error::Error::description(self))
+        match self {
+            Error::Message { ref msg, .. } => write!(formatter, "{}", msg),
+        }
     }
 }
 
-impl std::error::Error for Error {
-    fn description(&self) -> &str {
-        match *self {
-            Error::Message(ref msg) => msg,
+impl std::error::Error for Error {}
+
+/// Adds location information from `span`, if `res` is an error.
+pub fn set_location<T>(res: &mut Result<T>, span: &Span<'_>) {
+    if let Err(ref mut e) = res {
+        let Error::Message { location, .. } = e;
+        if location.is_none() {
+            let (line, column) = span.start_pos().line_col();
+            *location = Some(Location { line, column });
         }
     }
 }
diff --git a/third_party/src/lib.rs b/third_party/src/lib.rs
index 68d3e51..eaac541 100644
--- a/third_party/src/lib.rs
+++ b/third_party/src/lib.rs
@@ -123,5 +123,5 @@
 mod ser;
 
 pub use crate::de::from_str;
-pub use crate::error::{Error, Result};
+pub use crate::error::{Error, Location, Result};
 pub use crate::ser::to_string;
diff --git a/third_party/tests/common.rs b/third_party/tests/common.rs
index 4ed6e53..9eb1ff2 100644
--- a/third_party/tests/common.rs
+++ b/third_party/tests/common.rs
@@ -1,53 +1,41 @@
-use json5;
-use serde;
+use json5::{Error, Location};
+use matches::assert_matches;
 
-use std::f64;
-
-#[allow(dead_code)]
+#[allow(unused)]
 pub fn deserializes_to<'a, T>(s: &'a str, v: T)
 where
     T: ::std::fmt::Debug + ::std::cmp::PartialEq + serde::de::Deserialize<'a>,
 {
-    match json5::from_str::<T>(s) {
-        Ok(value) => assert_eq!(value, v),
-        Err(err) => panic!(format!("{}", err)),
-    }
+    assert_matches!(json5::from_str::<T>(s), Ok(value) if value == v);
 }
 
-#[allow(dead_code)]
+#[allow(unused)]
 pub fn deserializes_to_nan_f32<'a>(s: &'a str) {
-    match json5::from_str::<f32>(s) {
-        Ok(value) => assert!(value.is_nan()),
-        Err(err) => panic!(format!("{}", err)),
-    }
+    assert_matches!(json5::from_str::<f32>(s), Ok(value) if value.is_nan());
 }
 
-#[allow(dead_code)]
+#[allow(unused)]
 pub fn deserializes_to_nan_f64<'a>(s: &'a str) {
-    match json5::from_str::<f64>(s) {
-        Ok(value) => assert!(value.is_nan()),
-        Err(err) => panic!(format!("{}", err)),
-    }
+    assert_matches!(json5::from_str::<f64>(s), Ok(value) if value.is_nan());
 }
 
-#[allow(dead_code)]
-pub fn deserializes_with_error<'a, T>(s: &'a str, _: T, error_expected: &'a str)
+#[allow(unused)]
+pub fn deserializes_with_error<'a, T>(s: &'a str, error_expected: Error)
 where
     T: ::std::fmt::Debug + ::std::cmp::PartialEq + serde::de::Deserialize<'a>,
 {
-    match json5::from_str::<T>(s) {
-        Ok(val) => panic!(format!("error expected!, got {:?}", val)),
-        Err(err) => assert_eq!(format!("{}", err), error_expected),
-    }
+    assert_matches!(json5::from_str::<T>(s), Err(e) if e == error_expected);
 }
 
-#[allow(dead_code)]
+#[allow(unused)]
 pub fn serializes_to<T>(v: T, s: &'static str)
 where
     T: ::std::fmt::Debug + ::std::cmp::PartialEq + serde::ser::Serialize,
 {
-    match json5::to_string::<T>(&v) {
-        Ok(value) => assert_eq!(value, s),
-        Err(err) => panic!(format!("{}", err)),
-    }
+    assert_matches!(json5::to_string::<T>(&v), Ok(value) if value == s);
+}
+
+#[allow(unused)]
+pub fn make_error(msg: impl Into<String>, line: usize, column: usize) -> Error {
+    Error::Message { msg: msg.into(), location: Some(Location { line, column }) }
 }
diff --git a/third_party/tests/de.rs b/third_party/tests/de.rs
index 086b9fc..0474d8c 100644
--- a/third_party/tests/de.rs
+++ b/third_party/tests/de.rs
@@ -8,12 +8,46 @@
 
 use crate::common::{
     deserializes_to, deserializes_to_nan_f32, deserializes_to_nan_f64, deserializes_with_error,
+    make_error,
 };
 
+/// Defines a struct `A` with a `de::Deserializer` implementation that returns an error. Works for
+/// visitors that accept a single value.
+macro_rules! error_struct {
+    ($type:ty, $visit_fn:ident, $deserialize_fn:ident) => {
+        #[derive(Debug, PartialEq)]
+        struct A;
+        impl<'de> de::Deserialize<'de> for A {
+            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+            where
+                D: de::Deserializer<'de>,
+            {
+                struct Visitor;
+                impl<'de> de::Visitor<'de> for Visitor {
+                    type Value = A;
+                    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                        f.write_str("...")
+                    }
+                    fn $visit_fn<E>(self, _v: $type) -> Result<Self::Value, E>
+                    where
+                        E: de::Error,
+                    {
+                        Err(de::Error::custom("oops"))
+                    }
+                }
+                deserializer.$deserialize_fn(Visitor)
+            }
+        }
+    };
+}
+
 #[test]
 fn deserializes_bool() {
     deserializes_to("true", true);
     deserializes_to("false", false);
+
+    error_struct!(bool, visit_bool, deserialize_bool);
+    deserializes_with_error::<A>("\n true", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -38,6 +72,9 @@
     deserializes_to("-4.2e1", -x);
     deserializes_to("-.42e2", -x);
     deserializes_to("-0.42e2", -x);
+
+    error_struct!(i8, visit_i8, deserialize_i8);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -55,6 +92,9 @@
     deserializes_to("4.2e1", x);
     deserializes_to(".42e2", x);
     deserializes_to("0.42e2", x);
+
+    error_struct!(u8, visit_u8, deserialize_u8);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -79,6 +119,9 @@
     deserializes_to("-4.2e1", -x);
     deserializes_to("-.42e2", -x);
     deserializes_to("-0.42e2", -x);
+
+    error_struct!(i16, visit_i16, deserialize_i16);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -96,6 +139,9 @@
     deserializes_to("4.2e1", x);
     deserializes_to(".42e2", x);
     deserializes_to("0.42e2", x);
+
+    error_struct!(u16, visit_u16, deserialize_u16);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -120,6 +166,9 @@
     deserializes_to("-4.2e1", -x);
     deserializes_to("-.42e2", -x);
     deserializes_to("-0.42e2", -x);
+
+    error_struct!(i32, visit_i32, deserialize_i32);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -137,6 +186,9 @@
     deserializes_to("4.2e1", x);
     deserializes_to(".42e2", x);
     deserializes_to("0.42e2", x);
+
+    error_struct!(u32, visit_u32, deserialize_u32);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -161,6 +213,14 @@
     deserializes_to("-4.2e1", -x);
     deserializes_to("-.42e2", -x);
     deserializes_to("-0.42e2", -x);
+
+    error_struct!(i64, visit_i64, deserialize_i64);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
+    let over_i64 = format!("\n {}0", i64::max_value());
+    deserializes_with_error::<serde_json::Value>(
+        over_i64.as_str(),
+        make_error("error parsing integer", 2, 2),
+    );
 }
 
 #[test]
@@ -178,6 +238,13 @@
     deserializes_to("4.2e1", x);
     deserializes_to(".42e2", x);
     deserializes_to("0.42e2", x);
+
+    deserializes_to("Infinity", std::f32::INFINITY);
+    deserializes_to("-Infinity", std::f32::NEG_INFINITY);
+    deserializes_to_nan_f32("NaN");
+
+    error_struct!(u64, visit_u64, deserialize_u64);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -199,6 +266,9 @@
     deserializes_to("Infinity", std::f32::INFINITY);
     deserializes_to("-Infinity", std::f32::NEG_INFINITY);
     deserializes_to_nan_f32("NaN");
+
+    error_struct!(f32, visit_f32, deserialize_f32);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -220,6 +290,10 @@
     deserializes_to("Infinity", std::f64::INFINITY);
     deserializes_to("-Infinity", std::f64::NEG_INFINITY);
     deserializes_to_nan_f64("NaN");
+
+    error_struct!(f64, visit_f64, deserialize_f64);
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
+    deserializes_with_error::<f64>("\n 1e309", make_error("error parsing number: too large", 2, 2));
 }
 
 #[test]
@@ -234,6 +308,10 @@
     deserializes_to(r#""\/""#, '/');
     deserializes_to(r#""\b""#, '\u{0008}');
     deserializes_to(r#""\f""#, '\u{000c}');
+
+    // `deserialize_char` calls `visit_str`
+    error_struct!(&str, visit_str, deserialize_char);
+    deserializes_with_error::<A>("\n 'x'", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -247,6 +325,9 @@
 fn deserializes_string() {
     deserializes_to("'Hello!'", "Hello!".to_owned());
     deserializes_to("\"안녕하세요\"", "안녕하세요".to_owned());
+
+    error_struct!(&str, visit_str, deserialize_string);
+    deserializes_with_error::<A>("\n 'Hello!'", make_error("oops", 2, 2));
 }
 
 #[test]
@@ -265,18 +346,71 @@
 }
 
 #[test]
-fn deserializes_unit() {
-    deserializes_to("null", ());
+fn deserializes_option_error() {
+    #[derive(Debug, PartialEq)]
+    struct A;
+    impl<'de> de::Deserialize<'de> for A {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: de::Deserializer<'de>,
+        {
+            struct Visitor;
+            impl<'de> de::Visitor<'de> for Visitor {
+                type Value = A;
+                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    f.write_str("...")
+                }
+                fn visit_some<D>(self, _deserializer: D) -> Result<Self::Value, D::Error>
+                where
+                    D: de::Deserializer<'de>,
+                {
+                    Err(de::Error::custom("oops"))
+                }
+            }
+            deserializer.deserialize_option(Visitor)
+        }
+    }
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
 }
 
 #[test]
-fn deserializes_unit_struct() {
-    #[derive(Deserialize, PartialEq, Debug)]
+fn deserializes_unit() {
+    deserializes_to("null", ());
+
+    #[derive(Deserialize, Debug, PartialEq)]
     struct A;
     deserializes_to("null", A);
 }
 
 #[test]
+fn deserializes_unit_error() {
+    #[derive(Debug, PartialEq)]
+    struct A;
+    impl<'de> de::Deserialize<'de> for A {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: de::Deserializer<'de>,
+        {
+            struct Visitor;
+            impl<'de> de::Visitor<'de> for Visitor {
+                type Value = A;
+                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    f.write_str("...")
+                }
+                fn visit_unit<E>(self) -> Result<Self::Value, E>
+                where
+                    E: de::Error,
+                {
+                    Err(de::Error::custom("oops"))
+                }
+            }
+            deserializer.deserialize_unit(Visitor)
+        }
+    }
+    deserializes_with_error::<A>("\n null", make_error("oops", 2, 2));
+}
+
+#[test]
 fn deserializes_newtype_struct() {
     #[derive(Deserialize, PartialEq, Debug)]
     struct A(i32);
@@ -289,6 +423,34 @@
 }
 
 #[test]
+fn deserializes_newtype_struct_error() {
+    #[derive(Debug, PartialEq)]
+    struct A;
+    impl<'de> de::Deserialize<'de> for A {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: de::Deserializer<'de>,
+        {
+            struct Visitor;
+            impl<'de> de::Visitor<'de> for Visitor {
+                type Value = A;
+                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    f.write_str("...")
+                }
+                fn visit_newtype_struct<D>(self, _deserializer: D) -> Result<Self::Value, D::Error>
+                where
+                    D: de::Deserializer<'de>,
+                {
+                    Err(de::Error::custom("oops"))
+                }
+            }
+            deserializer.deserialize_newtype_struct("A", Visitor)
+        }
+    }
+    deserializes_with_error::<A>("\n 42", make_error("oops", 2, 2));
+}
+
+#[test]
 fn deserializes_seq() {
     #[derive(Deserialize, PartialEq, Debug)]
     #[serde(untagged)]
@@ -323,12 +485,12 @@
                 type Value = Size;
 
                 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    f.write_str("array")
+                    f.write_str("...")
                 }
 
                 fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
                 where
-                    A: serde::de::SeqAccess<'de>,
+                    A: de::SeqAccess<'de>,
                 {
                     Ok(Size(seq.size_hint().unwrap()))
                 }
@@ -343,6 +505,34 @@
 }
 
 #[test]
+fn deserializes_seq_error() {
+    #[derive(Debug, PartialEq)]
+    struct A;
+    impl<'de> de::Deserialize<'de> for A {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: de::Deserializer<'de>,
+        {
+            struct Visitor;
+            impl<'de> de::Visitor<'de> for Visitor {
+                type Value = A;
+                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    f.write_str("...")
+                }
+                fn visit_seq<A>(self, _a: A) -> Result<Self::Value, A::Error>
+                where
+                    A: de::SeqAccess<'de>,
+                {
+                    Err(de::Error::custom("oops"))
+                }
+            }
+            deserializer.deserialize_seq(Visitor)
+        }
+    }
+    deserializes_with_error::<A>("\n [ true ]", make_error("oops", 2, 2));
+}
+
+#[test]
 fn deserializes_tuple() {
     deserializes_to("[1, 2, 3]", (1, 2, 3));
 }
@@ -360,6 +550,41 @@
 }
 
 #[test]
+fn deserializes_tuple_error() {
+    #[derive(Debug, PartialEq)]
+    struct A;
+    impl<'de> de::Deserialize<'de> for A {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: de::Deserializer<'de>,
+        {
+            struct Visitor;
+            impl<'de> de::Visitor<'de> for Visitor {
+                type Value = A;
+                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    f.write_str("...")
+                }
+                fn visit_seq<A>(self, _a: A) -> Result<Self::Value, A::Error>
+                where
+                    A: de::SeqAccess<'de>,
+                {
+                    Err(de::Error::custom("oops"))
+                }
+            }
+            deserializer.deserialize_tuple(2, Visitor)
+        }
+    }
+    deserializes_with_error::<A>("\n [1, 2]", make_error("oops", 2, 2));
+
+    #[derive(Deserialize, Debug, PartialEq)]
+    struct B(i32, f64);
+    deserializes_with_error::<B>(
+        "\n [1]",
+        make_error("invalid length 1, expected tuple struct B with 2 elements", 2, 2),
+    );
+}
+
+#[test]
 fn deserializes_map() {
     let mut m = HashMap::new();
     m.insert("a".to_owned(), 1);
@@ -373,6 +598,7 @@
 fn deserializes_map_size_hint() {
     #[derive(Debug, PartialEq)]
     struct Size(usize);
+
     impl<'de> de::Deserialize<'de> for Size {
         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
         where
@@ -383,12 +609,12 @@
                 type Value = Size;
 
                 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    f.write_str("array")
+                    f.write_str("...")
                 }
 
                 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
                 where
-                    A: serde::de::MapAccess<'de>,
+                    A: de::MapAccess<'de>,
                 {
                     Ok(Size(map.size_hint().unwrap()))
                 }
@@ -403,6 +629,35 @@
 }
 
 #[test]
+fn deserializes_map_error() {
+    #[derive(Debug, PartialEq)]
+    struct A {}
+    impl<'de> de::Deserialize<'de> for A {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: de::Deserializer<'de>,
+        {
+            struct Visitor;
+            impl<'de> de::Visitor<'de> for Visitor {
+                type Value = A;
+                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    f.write_str("...")
+                }
+                fn visit_map<A>(self, _a: A) -> Result<Self::Value, A::Error>
+                where
+                    A: de::MapAccess<'de>,
+                {
+                    Err(de::Error::custom("oops"))
+                }
+            }
+            deserializer.deserialize_map(Visitor)
+        }
+    }
+
+    deserializes_with_error::<A>("\n { 'a': true }", make_error("oops", 2, 2));
+}
+
+#[test]
 fn deserializes_struct() {
     #[derive(Deserialize, PartialEq, Debug)]
     struct S {
@@ -415,6 +670,17 @@
 }
 
 #[test]
+fn deserializes_struct_error() {
+    #[derive(Deserialize, PartialEq, Debug)]
+    struct S {
+        a: i32,
+        b: i32,
+        c: i32,
+    }
+    deserializes_with_error::<S>("\n { a: 1, 'b': 2 }", make_error("missing field `c`", 2, 2));
+}
+
+#[test]
 fn deserializes_enum() {
     #[derive(Deserialize, PartialEq, Debug)]
     enum E {
@@ -435,7 +701,7 @@
 }
 
 #[test]
-fn deserializes_enum_with_error() {
+fn deserializes_enum_error() {
     #[derive(Deserialize, PartialEq, Debug)]
     enum E {
         A {},
@@ -447,8 +713,12 @@
         e: E,
     }
 
-    deserializes_with_error("{ e: 'A' }", S { e: E::A {} }, "expected an object");
-    deserializes_with_error("{ e: 'B' }", S { e: E::B() }, "expected an array");
+    deserializes_with_error::<S>("{ e: 'A' }", make_error("expected an object", 1, 6));
+    deserializes_with_error::<S>("{ e: 'B' }", make_error("expected an array", 1, 6));
+    deserializes_with_error::<E>(
+        "\n 'C'",
+        make_error("unknown variant `C`, expected `A` or `B`", 2, 2),
+    );
 }
 
 #[test]
@@ -478,22 +748,19 @@
 }
 
 #[test]
-fn deserialize_error_messages() {
+fn deserializes_parse_error() {
+    let parse_err_str = r#" --> 1:2
+  |
+1 | {
+  |  ^---
+  |
+  = expected identifier or string"#;
     #[derive(Deserialize, PartialEq, Debug)]
-    enum E {
-        A,
-    }
-    deserializes_with_error("'B'", E::A, "unknown variant `B`, expected `A`");
+    struct A;
+    deserializes_with_error::<A>("{", make_error(parse_err_str, 1, 2));
 
-    deserializes_with_error("0xffffffffff", 42, "error parsing hex");
-
-    let mut over_i64 = i64::max_value().to_string();
-    over_i64.push_str("0");
-    deserializes_with_error(
-        over_i64.as_str(),
-        serde_json::json!(42),
-        "error parsing integer",
+    deserializes_with_error::<bool>(
+        "\n 42",
+        make_error("invalid type: integer `42`, expected a boolean", 2, 2),
     );
-
-    deserializes_with_error("1e309", 42, "error parsing number: too large");
 }