about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-29 20:09:35 +0000
committerbors <bors@rust-lang.org>2017-09-29 20:09:35 +0000
commit6f87d20a7cce70b8cc59a1adf3037d14bc83f237 (patch)
tree76a82730a114bfbb9f6ee6b30e267a3b2c20b714
parent51cd06170eccf91a2d93018e939473a8db18da92 (diff)
parente30d92bb2d885629b51a5511b58109c94a1c56da (diff)
downloadrust-6f87d20a7cce70b8cc59a1adf3037d14bc83f237.tar.gz
rust-6f87d20a7cce70b8cc59a1adf3037d14bc83f237.zip
Auto merge of #42526 - huntiep:try_opt, r=nikomatsakis
Impl Try for Option

This is part of #31436.
-rw-r--r--src/libcore/option.rs28
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libcore/tests/option.rs27
-rw-r--r--src/libcore/tests/result.rs29
-rw-r--r--src/test/ui/suggestions/try-on-option.rs25
-rw-r--r--src/test/ui/suggestions/try-on-option.stderr22
6 files changed, 131 insertions, 1 deletions
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 138e04c7737..980ea551f08 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -146,7 +146,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use iter::{FromIterator, FusedIterator, TrustedLen};
-use mem;
+use {mem, ops};
 
 // Note that this is not a lang item per se, but it has a hidden dependency on
 // `Iterator`, which is one. The compiler assumes that the `next` method of
@@ -1123,3 +1123,29 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
         }
     }
 }
+
+/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish
+/// to allow `x?` (where `x` is an `Option<T>`) to be converted into your error type, you can
+/// implement `impl From<NoneError>` for `YourErrorType`. In that case, `x?` within a function that
+/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result.
+#[unstable(feature = "try_trait", issue = "42327")]
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+pub struct NoneError;
+
+#[unstable(feature = "try_trait", issue = "42327")]
+impl<T> ops::Try for Option<T> {
+    type Ok = T;
+    type Error = NoneError;
+
+    fn into_result(self) -> Result<T, NoneError> {
+        self.ok_or(NoneError)
+    }
+
+    fn from_ok(v: T) -> Self {
+        Some(v)
+    }
+
+    fn from_error(_: NoneError) -> Self {
+        None
+    }
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index d928276ad2f..afc5de7b0ee 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -39,6 +39,7 @@
 #![feature(test)]
 #![feature(trusted_len)]
 #![feature(try_from)]
+#![feature(try_trait)]
 #![feature(unique)]
 
 #![feature(const_atomic_bool_new)]
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index 6bac55575fb..22109e28edd 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -270,3 +270,30 @@ fn test_cloned() {
     assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
     assert_eq!(opt_ref_ref.cloned().cloned(), Some(1));
 }
+
+#[test]
+fn test_try() {
+    fn try_option_some() -> Option<u8> {
+        let val = Some(1)?;
+        Some(val)
+    }
+    assert_eq!(try_option_some(), Some(1));
+
+    fn try_option_none() -> Option<u8> {
+        let val = None?;
+        Some(val)
+    }
+    assert_eq!(try_option_none(), None);
+
+    fn try_option_ok() -> Result<u8, NoneError> {
+        let val = Some(1)?;
+        Ok(val)
+    }
+    assert_eq!(try_option_ok(), Ok(1));
+
+    fn try_option_err() -> Result<u8, NoneError> {
+        let val = None?;
+        Ok(val)
+    }
+    assert_eq!(try_option_err(), Err(NoneError));
+}
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index 4c5f19dee12..ce41bde8342 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use core::option::*;
+
 fn op1() -> Result<isize, &'static str> { Ok(666) }
 fn op2() -> Result<isize, &'static str> { Err("sadface") }
 
@@ -202,3 +204,30 @@ pub fn test_unwrap_or_default() {
     assert_eq!(op1().unwrap_or_default(), 666);
     assert_eq!(op2().unwrap_or_default(), 0);
 }
+
+#[test]
+fn test_try() {
+    fn try_result_some() -> Option<u8> {
+        let val = Ok(1)?;
+        Some(val)
+    }
+    assert_eq!(try_result_some(), Some(1));
+
+    fn try_result_none() -> Option<u8> {
+        let val = Err(NoneError)?;
+        Some(val)
+    }
+    assert_eq!(try_result_none(), None);
+
+    fn try_result_ok() -> Result<u8, u8> {
+        let val = Ok(1)?;
+        Ok(val)
+    }
+    assert_eq!(try_result_ok(), Ok(1));
+
+    fn try_result_err() -> Result<u8, u8> {
+        let val = Err(1)?;
+        Ok(val)
+    }
+    assert_eq!(try_result_err(), Err(1));
+}
diff --git a/src/test/ui/suggestions/try-on-option.rs b/src/test/ui/suggestions/try-on-option.rs
new file mode 100644
index 00000000000..4cd8cd81151
--- /dev/null
+++ b/src/test/ui/suggestions/try-on-option.rs
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(try_trait)]
+
+fn main() {}
+
+fn foo() -> Result<u32, ()> {
+    let x: Option<u32> = None;
+    x?;
+    Ok(22)
+}
+
+fn bar() -> u32 {
+    let x: Option<u32> = None;
+    x?;
+    22
+}
diff --git a/src/test/ui/suggestions/try-on-option.stderr b/src/test/ui/suggestions/try-on-option.stderr
new file mode 100644
index 00000000000..86d4510cad3
--- /dev/null
+++ b/src/test/ui/suggestions/try-on-option.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `(): std::convert::From<std::option::NoneError>` is not satisfied
+  --> $DIR/try-on-option.rs:17:5
+   |
+17 |     x?;
+   |     ^^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
+   |
+   = note: required by `std::convert::From::from`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option.rs:23:5
+   |
+23 |     x?;
+   |     --
+   |     |
+   |     cannot use the `?` operator in a function that returns `u32`
+   |     in this macro invocation
+   |
+   = help: the trait `std::ops::Try` is not implemented for `u32`
+   = note: required by `std::ops::Try::from_error`
+
+error: aborting due to 2 previous errors
+