about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-03-27 11:50:10 +0000
committerbors <bors@rust-lang.org>2018-03-27 11:50:10 +0000
commit3efe61c825e1d49dc6febeb252954b9532c0c677 (patch)
tree344ae0b1c79ccf598fde261fce7fa23bf56f7cb8 /src/libstd
parent14ac1b5faab32d268a85dfde6c6592b7183c5864 (diff)
parent837d6c70233715a0ae8e15c703d40e3046a2f36a (diff)
downloadrust-3efe61c825e1d49dc6febeb252954b9532c0c677.tar.gz
rust-3efe61c825e1d49dc6febeb252954b9532c0c677.zip
Auto merge of #49305 - SimonSapin:fallible, r=sfackler
Stabilize TryFrom / TryInto, and tweak impls for integers

Fixes https://github.com/rust-lang/rust/issues/33417 (tracking issue)

----

This adds:

* `impl From<u16> for usize`
* `impl From<i16> for isize`
* `impl From<u8> for isize`

… replacing corresponding `TryFrom<Error=!>` impls. (`TryFrom` still applies through the generic `impl<T, U> TryFrom<U> for T where T: From<U>`.) Their infallibility is supported by the C99 standard which (indirectly) requires pointers to be at least 16 bits.

The remaining `TryFrom` impls that define `type Error = !` all involve `usize` or `isize`. This PR changes them to use `TryFromIntError` instead, since having a return type change based on the target is a portability hazard.

Note: if we make similar assumptions about the *maximum* bit size of pointers (for all targets Rust will ever run on in the future), we could have similar `From` impls converting pointer-sized integers to large fixed-size integers. RISC-V considers the possibility of a 128-bit address space (RV128), which would leave only `impl From<usize> for u128` and `impl From<isize> for u128`. I [found](https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf) some [things](http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf) about 256-bit “capabilities”, but I don’t know how relevant that would be to Rust’s `usize` and `isize` types.

I chose conservatively to make no assumption about the future there. Users making their portability decisions and using something like `.try_into().unwrap()`.

----

Since this feature already went through FCP in the tracking issue https://github.com/rust-lang/rust/issues/33417, this PR also proposes **stabilize** the following items:

* The `convert::TryFrom` trait
* The `convert::TryFrom` trait
* `impl<T> TryFrom<&[T]> for &[T; $N]` (for `$N` up to 32)
* `impl<T> TryFrom<&mut [T]> for &mut [T; $N]` (for `$N` up to 32)
* The `array::TryFromSliceError` struct, with impls of `Debug`, `Copy`, `Clone`, and `Error`
* `impl TryFrom<u32> for char`
* The `char::CharTryFromError` struct, with impls of `Copy`, `Clone`, `Debug`, `PartialEq`, `Eq`, `Display`, and `Error`
* Impls of `TryFrom` for all (?) combinations of primitive integer types where `From` isn’t implemented.
* The `num::TryFromIntError` struct, with impls of `Debug`, `Copy`, `Clone`, `Display`, `From<!>`, and `Error`

Some minor remaining questions that I hope can be resolved in this PR:

* Should the impls for error types be unified?
* ~Should `TryFrom` and `TryInto` be in the prelude? `From` and `Into` are.~ (Yes.)
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/error.rs6
-rw-r--r--src/libstd/io/cursor.rs20
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/prelude/v1.rs2
4 files changed, 23 insertions, 6 deletions
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 79bb6af168f..3d0c96585b5 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -275,14 +275,14 @@ impl Error for num::ParseIntError {
     }
 }
 
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
 impl Error for num::TryFromIntError {
     fn description(&self) -> &str {
         self.__description()
     }
 }
 
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
 impl Error for array::TryFromSliceError {
     fn description(&self) -> &str {
         self.__description()
@@ -356,7 +356,7 @@ impl Error for cell::BorrowMutError {
     }
 }
 
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
 impl Error for char::CharTryFromError {
     fn description(&self) -> &str {
         "converted integer out of range for `char`"
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 76bcb5fedc9..2673f3ccfa3 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -10,7 +10,6 @@
 
 use io::prelude::*;
 
-use core::convert::TryInto;
 use cmp;
 use io::{self, Initializer, SeekFrom, Error, ErrorKind};
 
@@ -260,9 +259,26 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<us
     Ok(amt)
 }
 
+/// Compensate removal of some impls per
+/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243
+#[cfg(any(target_pointer_width = "16",
+          target_pointer_width = "32"))]
+fn try_into(n: u64) -> Result<usize, ()> {
+    if n <= (<usize>::max_value() as u64) {
+        Ok(n as usize)
+    } else {
+        Err(())
+    }
+}
+
+#[cfg(any(target_pointer_width = "64"))]
+fn try_into(n: u64) -> Result<usize, ()> {
+    Ok(n as usize)
+}
+
 // Resizing write implementation
 fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
-    let pos: usize = (*pos_mut).try_into().map_err(|_| {
+    let pos: usize = try_into(*pos_mut).map_err(|_| {
         Error::new(ErrorKind::InvalidInput,
                     "cursor position exceeds maximum possible vector length")
     })?;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 93996868f16..15a22443b6a 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -310,7 +310,6 @@
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
-#![feature(try_from)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index feedd4e1abe..d5b7c68a3fa 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -35,6 +35,8 @@
 #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From};
+#[stable(feature = "try_from", since = "1.26.0")]
+#[doc(no_inline)] pub use convert::{TryFrom, TryInto};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use default::Default;
 #[stable(feature = "rust1", since = "1.0.0")]