about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/fs.rs8
-rw-r--r--library/std/src/io/buffered/bufreader.rs2
-rw-r--r--library/std/src/io/error.rs12
-rw-r--r--library/std/src/io/impls.rs4
-rw-r--r--library/std/src/io/mod.rs4
-rw-r--r--library/std/src/io/tests.rs10
6 files changed, 31 insertions, 9 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 4373a1721e1..5d0de2d06a0 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -261,7 +261,7 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
         let mut file = File::open(path)?;
         let size = file.metadata().map(|m| m.len() as usize).ok();
         let mut bytes = Vec::new();
-        bytes.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?;
+        bytes.try_reserve_exact(size.unwrap_or(0))?;
         io::default_read_to_end(&mut file, &mut bytes, size)?;
         Ok(bytes)
     }
@@ -304,7 +304,7 @@ pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
         let mut file = File::open(path)?;
         let size = file.metadata().map(|m| m.len() as usize).ok();
         let mut string = String::new();
-        string.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?;
+        string.try_reserve_exact(size.unwrap_or(0))?;
         io::default_read_to_string(&mut file, &mut string, size)?;
         Ok(string)
     }
@@ -777,14 +777,14 @@ impl Read for &File {
     // Reserves space in the buffer based on the file size when available.
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
         let size = buffer_capacity_required(self);
-        buf.try_reserve(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?;
+        buf.try_reserve(size.unwrap_or(0))?;
         io::default_read_to_end(self, buf, size)
     }
 
     // Reserves space in the buffer based on the file size when available.
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
         let size = buffer_capacity_required(self);
-        buf.try_reserve(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?;
+        buf.try_reserve(size.unwrap_or(0))?;
         io::default_read_to_string(self, buf, size)
     }
 }
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index e0dc9f96ae9..83db332ee25 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -344,7 +344,7 @@ impl<R: ?Sized + Read> Read for BufReader<R> {
     // delegate to the inner implementation.
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
         let inner_buf = self.buffer();
-        buf.try_reserve(inner_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?;
+        buf.try_reserve(inner_buf.len())?;
         buf.extend_from_slice(inner_buf);
         let nread = inner_buf.len();
         self.discard_buffer();
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 13cc0511e10..7ae15e0fd01 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -83,6 +83,18 @@ impl From<alloc::ffi::NulError> for Error {
     }
 }
 
+#[stable(feature = "io_error_from_try_reserve", since = "CURRENT_RUSTC_VERSION")]
+impl From<alloc::collections::TryReserveError> for Error {
+    /// Converts `TryReserveError` to an error with [`ErrorKind::OutOfMemory`].
+    ///
+    /// `TryReserveError` won't be available as the error `source()`,
+    /// but this may change in the future.
+    fn from(_: alloc::collections::TryReserveError) -> Error {
+        // ErrorData::Custom allocates, which isn't great for handling OOM errors.
+        ErrorKind::OutOfMemory.into()
+    }
+}
+
 // Only derive debug in tests, to make sure it
 // doesn't accidentally get printed.
 #[cfg_attr(test, derive(Debug))]
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 557e64dc867..cb972abd2b8 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -304,7 +304,7 @@ impl Read for &[u8] {
     #[inline]
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
         let len = self.len();
-        buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?;
+        buf.try_reserve(len)?;
         buf.extend_from_slice(*self);
         *self = &self[len..];
         Ok(len)
@@ -452,7 +452,7 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
         // The total len is known upfront so we can reserve it in a single call.
         let len = self.len();
-        buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?;
+        buf.try_reserve(len)?;
 
         let (front, back) = self.as_slices();
         buf.extend_from_slice(front);
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index f35bffd6a3c..9a4a2301b6f 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -465,7 +465,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(
 
         if buf.len() == buf.capacity() {
             // buf is full, need more space
-            buf.try_reserve(PROBE_SIZE).map_err(|_| ErrorKind::OutOfMemory)?;
+            buf.try_reserve(PROBE_SIZE)?;
         }
 
         let mut spare = buf.spare_capacity_mut();
@@ -834,7 +834,7 @@ pub trait Read {
     ///         if src_buf.is_empty() {
     ///             break;
     ///         }
-    ///         dest_vec.try_reserve(src_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?;
+    ///         dest_vec.try_reserve(src_buf.len())?;
     ///         dest_vec.extend_from_slice(src_buf);
     ///
     ///         // Any irreversible side effects should happen after `try_reserve` succeeds,
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index 5396f7f6e21..c306de3039f 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -692,3 +692,13 @@ fn read_buf_full_read() {
 
     assert_eq!(BufReader::new(FullRead).fill_buf().unwrap().len(), DEFAULT_BUF_SIZE);
 }
+
+#[test]
+// 64-bit only to be sure the allocator will fail fast on an impossible to satsify size
+#[cfg(target_pointer_width = "64")]
+fn try_oom_error() {
+    let mut v = Vec::<u8>::new();
+    let reserve_err = v.try_reserve(isize::MAX as usize - 1).unwrap_err();
+    let io_err = io::Error::from(reserve_err);
+    assert_eq!(io::ErrorKind::OutOfMemory, io_err.kind());
+}