diff options
| author | bors <bors@rust-lang.org> | 2017-09-29 20:09:35 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-09-29 20:09:35 +0000 |
| commit | 6f87d20a7cce70b8cc59a1adf3037d14bc83f237 (patch) | |
| tree | 76a82730a114bfbb9f6ee6b30e267a3b2c20b714 | |
| parent | 51cd06170eccf91a2d93018e939473a8db18da92 (diff) | |
| parent | e30d92bb2d885629b51a5511b58109c94a1c56da (diff) | |
| download | rust-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.rs | 28 | ||||
| -rw-r--r-- | src/libcore/tests/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcore/tests/option.rs | 27 | ||||
| -rw-r--r-- | src/libcore/tests/result.rs | 29 | ||||
| -rw-r--r-- | src/test/ui/suggestions/try-on-option.rs | 25 | ||||
| -rw-r--r-- | src/test/ui/suggestions/try-on-option.stderr | 22 |
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 + |
