about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-01-21 02:21:53 +0100
committerGitHub <noreply@github.com>2019-01-21 02:21:53 +0100
commitebc70e2e9ecdd0920c5e78f53ed694f1c050c5ed (patch)
tree7b5c2dc6e750f5f8e0e9ca86920761b95cc8e534
parente73069767f11d992f0dca7e31d53d7e1a77fd237 (diff)
parentea68b3ff3dd5a49c5984c476570fb5404c342079 (diff)
downloadrust-ebc70e2e9ecdd0920c5e78f53ed694f1c050c5ed.tar.gz
rust-ebc70e2e9ecdd0920c5e78f53ed694f1c050c5ed.zip
Rollup merge of #56796 - KrishnaSannasi:try_from_impl_change, r=shepmaster
Change bounds on `TryFrom` blanket impl to use `Into` instead of `From`

This is from this [comment](https://github.com/rust-lang/rust/issues/33417#issuecomment-447111156) I made.

This will expand the impls available for `TryFrom` and `TryInto`, without losing anything in the process.
-rw-r--r--src/libcore/convert.rs4
-rw-r--r--src/test/run-pass/try_from.rs37
-rw-r--r--src/test/ui/e0119/conflict-with-std.stderr2
3 files changed, 40 insertions, 3 deletions
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 08b5ac06f72..203be541e49 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -463,11 +463,11 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
 // Infallible conversions are semantically equivalent to fallible conversions
 // with an uninhabited error type.
 #[unstable(feature = "try_from", issue = "33417")]
-impl<T, U> TryFrom<U> for T where T: From<U> {
+impl<T, U> TryFrom<U> for T where U: Into<T> {
     type Error = !;
 
     fn try_from(value: U) -> Result<Self, Self::Error> {
-        Ok(T::from(value))
+        Ok(U::into(value))
     }
 }
 
diff --git a/src/test/run-pass/try_from.rs b/src/test/run-pass/try_from.rs
new file mode 100644
index 00000000000..4522ce3a8d6
--- /dev/null
+++ b/src/test/run-pass/try_from.rs
@@ -0,0 +1,37 @@
+// This test relies on `TryFrom` being blanket impl for all `T: Into`
+// and `TryInto` being blanket impl for all `U: TryFrom`
+
+// This test was added to show the motivation for doing this
+// over `TryFrom` being blanket impl for all `T: From`
+
+#![feature(try_from, never_type)]
+
+use std::convert::TryInto;
+
+struct Foo<T> {
+    t: T,
+}
+
+// This fails to compile due to coherence restrictions
+// as of Rust version 1.32.x, therefore it could not be used
+// instead of the `Into` version of the impl, and serves as
+// motivation for a blanket impl for all `T: Into`, instead
+// of a blanket impl for all `T: From`
+/*
+impl<T> From<Foo<T>> for Box<T> {
+    fn from(foo: Foo<T>) -> Box<T> {
+        Box::new(foo.t)
+    }
+}
+*/
+
+impl<T> Into<Vec<T>> for Foo<T> {
+    fn into(self) -> Vec<T> {
+        vec![self.t]
+    }
+}
+
+pub fn main() {
+    let _: Result<Vec<i32>, !> = Foo { t: 10 }.try_into();
+}
+
diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr
index d94e4dc5b6e..c2ae321aa5e 100644
--- a/src/test/ui/e0119/conflict-with-std.stderr
+++ b/src/test/ui/e0119/conflict-with-std.stderr
@@ -25,7 +25,7 @@ LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations
    |
    = note: conflicting implementation in crate `core`:
            - impl<T, U> std::convert::TryFrom<U> for T
-             where T: std::convert::From<U>;
+             where U: std::convert::Into<T>;
 
 error: aborting due to 3 previous errors