Skip to content

Commit 6f87d20

Browse files
committed
Auto merge of #42526 - huntiep:try_opt, r=nikomatsakis
Impl Try for Option This is part of #31436.
2 parents 51cd061 + e30d92b commit 6f87d20

File tree

6 files changed

+131
-1
lines changed

6 files changed

+131
-1
lines changed

src/libcore/option.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
#![stable(feature = "rust1", since = "1.0.0")]
147147

148148
use iter::{FromIterator, FusedIterator, TrustedLen};
149-
use mem;
149+
use {mem, ops};
150150

151151
// Note that this is not a lang item per se, but it has a hidden dependency on
152152
// `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> {
11231123
}
11241124
}
11251125
}
1126+
1127+
/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish
1128+
/// to allow `x?` (where `x` is an `Option<T>`) to be converted into your error type, you can
1129+
/// implement `impl From<NoneError>` for `YourErrorType`. In that case, `x?` within a function that
1130+
/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result.
1131+
#[unstable(feature = "try_trait", issue = "42327")]
1132+
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
1133+
pub struct NoneError;
1134+
1135+
#[unstable(feature = "try_trait", issue = "42327")]
1136+
impl<T> ops::Try for Option<T> {
1137+
type Ok = T;
1138+
type Error = NoneError;
1139+
1140+
fn into_result(self) -> Result<T, NoneError> {
1141+
self.ok_or(NoneError)
1142+
}
1143+
1144+
fn from_ok(v: T) -> Self {
1145+
Some(v)
1146+
}
1147+
1148+
fn from_error(_: NoneError) -> Self {
1149+
None
1150+
}
1151+
}

src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#![feature(test)]
4040
#![feature(trusted_len)]
4141
#![feature(try_from)]
42+
#![feature(try_trait)]
4243
#![feature(unique)]
4344

4445
#![feature(const_atomic_bool_new)]

src/libcore/tests/option.rs

+27
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,30 @@ fn test_cloned() {
270270
assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
271271
assert_eq!(opt_ref_ref.cloned().cloned(), Some(1));
272272
}
273+
274+
#[test]
275+
fn test_try() {
276+
fn try_option_some() -> Option<u8> {
277+
let val = Some(1)?;
278+
Some(val)
279+
}
280+
assert_eq!(try_option_some(), Some(1));
281+
282+
fn try_option_none() -> Option<u8> {
283+
let val = None?;
284+
Some(val)
285+
}
286+
assert_eq!(try_option_none(), None);
287+
288+
fn try_option_ok() -> Result<u8, NoneError> {
289+
let val = Some(1)?;
290+
Ok(val)
291+
}
292+
assert_eq!(try_option_ok(), Ok(1));
293+
294+
fn try_option_err() -> Result<u8, NoneError> {
295+
let val = None?;
296+
Ok(val)
297+
}
298+
assert_eq!(try_option_err(), Err(NoneError));
299+
}

src/libcore/tests/result.rs

+29
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use core::option::*;
12+
1113
fn op1() -> Result<isize, &'static str> { Ok(666) }
1214
fn op2() -> Result<isize, &'static str> { Err("sadface") }
1315

@@ -202,3 +204,30 @@ pub fn test_unwrap_or_default() {
202204
assert_eq!(op1().unwrap_or_default(), 666);
203205
assert_eq!(op2().unwrap_or_default(), 0);
204206
}
207+
208+
#[test]
209+
fn test_try() {
210+
fn try_result_some() -> Option<u8> {
211+
let val = Ok(1)?;
212+
Some(val)
213+
}
214+
assert_eq!(try_result_some(), Some(1));
215+
216+
fn try_result_none() -> Option<u8> {
217+
let val = Err(NoneError)?;
218+
Some(val)
219+
}
220+
assert_eq!(try_result_none(), None);
221+
222+
fn try_result_ok() -> Result<u8, u8> {
223+
let val = Ok(1)?;
224+
Ok(val)
225+
}
226+
assert_eq!(try_result_ok(), Ok(1));
227+
228+
fn try_result_err() -> Result<u8, u8> {
229+
let val = Err(1)?;
230+
Ok(val)
231+
}
232+
assert_eq!(try_result_err(), Err(1));
233+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(try_trait)]
12+
13+
fn main() {}
14+
15+
fn foo() -> Result<u32, ()> {
16+
let x: Option<u32> = None;
17+
x?;
18+
Ok(22)
19+
}
20+
21+
fn bar() -> u32 {
22+
let x: Option<u32> = None;
23+
x?;
24+
22
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: the trait bound `(): std::convert::From<std::option::NoneError>` is not satisfied
2+
--> $DIR/try-on-option.rs:17:5
3+
|
4+
17 | x?;
5+
| ^^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
6+
|
7+
= note: required by `std::convert::From::from`
8+
9+
error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
10+
--> $DIR/try-on-option.rs:23:5
11+
|
12+
23 | x?;
13+
| --
14+
| |
15+
| cannot use the `?` operator in a function that returns `u32`
16+
| in this macro invocation
17+
|
18+
= help: the trait `std::ops::Try` is not implemented for `u32`
19+
= note: required by `std::ops::Try::from_error`
20+
21+
error: aborting due to 2 previous errors
22+

0 commit comments

Comments
 (0)