]> git.lizzy.rs Git - rust.git/commitdiff
move debug_map assertions after check for err
authorAshley Mannix <ashleymannix@live.com.au>
Wed, 9 Oct 2019 14:24:45 +0000 (00:24 +1000)
committerAshley Mannix <ashleymannix@live.com.au>
Thu, 10 Oct 2019 00:01:47 +0000 (10:01 +1000)
src/libcore/fmt/builders.rs
src/libcore/tests/fmt/builders.rs

index 15ce2277fa00d9188aad74dc7043f72faa149a3e..e6e3454b36f810bb96cf2c525059182aa3eb69c9 100644 (file)
@@ -775,10 +775,10 @@ pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut De
                reason = "recently added",
                issue = "62482")]
     pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
-        assert!(!self.has_key, "attempted to begin a new map entry \
-                                without completing the previous one");
-
         self.result = self.result.and_then(|_| {
+            assert!(!self.has_key, "attempted to begin a new map entry \
+                                    without completing the previous one");
+
             if self.is_pretty() {
                 if !self.has_fields {
                     self.fmt.write_str("\n")?;
@@ -839,9 +839,9 @@ pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
                reason = "recently added",
                issue = "62482")]
     pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
-        assert!(self.has_key, "attempted to format a map value before its key");
-
         self.result = self.result.and_then(|_| {
+            assert!(self.has_key, "attempted to format a map value before its key");
+
             if self.is_pretty() {
                 let mut slot = None;
                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut self.state);
@@ -924,9 +924,11 @@ pub fn entries<K, V, I>(&mut self, entries: I) -> &mut DebugMap<'a, 'b>
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        assert!(!self.has_key, "attempted to finish a map with a partial entry");
+        self.result.and_then(|_| {
+            assert!(!self.has_key, "attempted to finish a map with a partial entry");
 
-        self.result.and_then(|_| self.fmt.write_str("}"))
+            self.fmt.write_str("}")
+        })
     }
 
     fn is_pretty(&self) -> bool {
index 200659b91bb4ec696697e0423347c4fbb720cb3c..255724432816d99ea2d96ebe5dd036ad9bc6c1b3 100644 (file)
@@ -319,6 +319,46 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
                    format!("{:#?}", Bar));
     }
 
+    #[test]
+    fn test_entry_err() {
+        // Ensure errors in a map entry don't trigger panics (#65231)
+        use std::fmt::Write;
+
+        struct ErrorFmt;
+
+        impl fmt::Debug for ErrorFmt {
+            fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
+                Err(fmt::Error)
+            }
+        }
+
+        struct KeyValue<K, V>(usize, K, V);
+
+        impl<K, V> fmt::Debug for KeyValue<K, V>
+        where
+            K: fmt::Debug,
+            V: fmt::Debug,
+        {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                let mut map = fmt.debug_map();
+
+                for _ in 0..self.0 {
+                    map.entry(&self.1, &self.2);
+                }
+
+                map.finish()
+            }
+        }
+
+        let mut buf = String::new();
+
+        assert!(write!(&mut buf, "{:?}", KeyValue(1, ErrorFmt, "bar")).is_err());
+        assert!(write!(&mut buf, "{:?}", KeyValue(1, "foo", ErrorFmt)).is_err());
+
+        assert!(write!(&mut buf, "{:?}", KeyValue(2, ErrorFmt, "bar")).is_err());
+        assert!(write!(&mut buf, "{:?}", KeyValue(2, "foo", ErrorFmt)).is_err());
+    }
+
     #[test]
     #[should_panic]
     fn test_invalid_key_when_entry_is_incomplete() {