Skip to content

Commit ecde1e1

Browse files
committed
Lower ? to Try instead of Carrier
The easy parts of RFC 1859. (Just the trait and the lowering, none of the error message improvements nor the insta-stable impl for Option.)
1 parent ffb0e2d commit ecde1e1

File tree

7 files changed

+95
-33
lines changed

7 files changed

+95
-33
lines changed

src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
- [toowned_clone_into](library-features/toowned-clone-into.md)
209209
- [trusted_len](library-features/trusted-len.md)
210210
- [try_from](library-features/try-from.md)
211+
- [try_trait](library-features/try-trait.md)
211212
- [unicode](library-features/unicode.md)
212213
- [unique](library-features/unique.md)
213214
- [unsize](library-features/unsize.md)

src/doc/unstable-book/src/library-features/question-mark-carrier.md

+6
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ The tracking issue for this feature is: [#31436]
55
[#31436]: https://github.com/rust-lang/rust/issues/31436
66

77
------------------------
8+
9+
This feature has been superseded by [`try_trait`][try_trait].
10+
11+
It exists only in stage0 for bootstrapping.
12+
13+
[try_trait]: library-features/try-trait.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `try_trait`
2+
3+
The tracking issue for this feature is: [#31436]
4+
5+
[#31436]: https://github.com/rust-lang/rust/issues/31436
6+
7+
------------------------

src/libcore/ops.rs

+48-17
Original file line numberDiff line numberDiff line change
@@ -2918,15 +2918,9 @@ pub trait BoxPlace<Data: ?Sized> : Place<Data> {
29182918
fn make_place() -> Self;
29192919
}
29202920

2921-
/// A trait for types which have success and error states and are meant to work
2922-
/// with the question mark operator.
2923-
/// When the `?` operator is used with a value, whether the value is in the
2924-
/// success or error state is determined by calling `translate`.
2925-
///
2926-
/// This trait is **very** experimental, it will probably be iterated on heavily
2927-
/// before it is stabilised. Implementors should expect change. Users of `?`
2928-
/// should not rely on any implementations of `Carrier` other than `Result`,
2929-
/// i.e., you should not expect `?` to continue to work with `Option`, etc.
2921+
/// This trait has been superseded by the `Try` trait, but must remain
2922+
/// here as `?` is still lowered to it in stage0 .
2923+
#[cfg(stage0)]
29302924
#[unstable(feature = "question_mark_carrier", issue = "31436")]
29312925
pub trait Carrier {
29322926
/// The type of the value when computation succeeds.
@@ -2945,6 +2939,7 @@ pub trait Carrier {
29452939
fn translate<T>(self) -> T where T: Carrier<Success=Self::Success, Error=Self::Error>;
29462940
}
29472941

2942+
#[cfg(stage0)]
29482943
#[unstable(feature = "question_mark_carrier", issue = "31436")]
29492944
impl<U, V> Carrier for Result<U, V> {
29502945
type Success = U;
@@ -2970,21 +2965,57 @@ impl<U, V> Carrier for Result<U, V> {
29702965

29712966
struct _DummyErrorType;
29722967

2973-
impl Carrier for _DummyErrorType {
2974-
type Success = ();
2968+
impl Try for _DummyErrorType {
2969+
type Ok = ();
29752970
type Error = ();
29762971

2977-
fn from_success(_: ()) -> _DummyErrorType {
2972+
fn into_result(self) -> Result<Self::Ok, Self::Error> {
2973+
Ok(())
2974+
}
2975+
2976+
fn from_ok(_: ()) -> _DummyErrorType {
29782977
_DummyErrorType
29792978
}
29802979

29812980
fn from_error(_: ()) -> _DummyErrorType {
29822981
_DummyErrorType
29832982
}
2983+
}
29842984

2985-
fn translate<T>(self) -> T
2986-
where T: Carrier<Success=(), Error=()>
2987-
{
2988-
T::from_success(())
2989-
}
2985+
/// A trait for customizing the behaviour of the `?` operator.
2986+
///
2987+
/// A type implementing `Try` is one that has a canonical way to view it
2988+
/// in terms of a success/failure dichotomy. This trait allows both
2989+
/// extracting those success or failure values from an existing instance and
2990+
/// creating a new instance from a success or failure value.
2991+
#[unstable(feature = "try_trait", issue = "31436")]
2992+
pub trait Try {
2993+
/// The type of this value when viewed as successful.
2994+
#[unstable(feature = "try_trait", issue = "31436")]
2995+
type Ok;
2996+
/// The type of this value when viewed as failed.
2997+
#[unstable(feature = "try_trait", issue = "31436")]
2998+
type Error;
2999+
3000+
/// Applies the "?" operator. A return of `Ok(t)` means that the
3001+
/// execution should continue normally, and the result of `?` is the
3002+
/// value `t`. A return of `Err(e)` means that execution should branch
3003+
/// to the innermost enclosing `catch`, or return from the function.
3004+
///
3005+
/// If an `Err(e)` result is returned, the value `e` will be "wrapped"
3006+
/// in the return type of the enclosing scope (which must itself implement
3007+
/// `Try`). Specifically, the value `X::from_error(From::from(e))`
3008+
/// is returned, where `X` is the return type of the enclosing function.
3009+
#[unstable(feature = "try_trait", issue = "31436")]
3010+
fn into_result(self) -> Result<Self::Ok, Self::Error>;
3011+
3012+
/// Wrap an error value to construct the composite result. For example,
3013+
/// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
3014+
#[unstable(feature = "try_trait", issue = "31436")]
3015+
fn from_error(v: Self::Error) -> Self;
3016+
3017+
/// Wrap an OK value to construct the composite result. For example,
3018+
/// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
3019+
#[unstable(feature = "try_trait", issue = "31436")]
3020+
fn from_ok(v: Self::Ok) -> Self;
29903021
}

src/libcore/result.rs

+19
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@
242242

243243
use fmt;
244244
use iter::{FromIterator, FusedIterator, TrustedLen};
245+
use ops;
245246

246247
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
247248
///
@@ -1108,3 +1109,21 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
11081109
}
11091110
}
11101111
}
1112+
1113+
#[unstable(feature = "try_trait", issue = "31436")]
1114+
impl<T,E> ops::Try for Result<T, E> {
1115+
type Ok = T;
1116+
type Error = E;
1117+
1118+
fn into_result(self) -> Self {
1119+
self
1120+
}
1121+
1122+
fn from_ok(v: T) -> Self {
1123+
Ok(v)
1124+
}
1125+
1126+
fn from_error(v: E) -> Self {
1127+
Err(v)
1128+
}
1129+
}

src/librustc/hir/lowering.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -2244,23 +2244,23 @@ impl<'a> LoweringContext<'a> {
22442244
ExprKind::Try(ref sub_expr) => {
22452245
// to:
22462246
//
2247-
// match Carrier::translate(<expr>) {
2247+
// match Try::into_result(<expr>) {
22482248
// Ok(val) => #[allow(unreachable_code)] val,
22492249
// Err(err) => #[allow(unreachable_code)]
22502250
// // If there is an enclosing `catch {...}`
2251-
// break 'catch_target Carrier::from_error(From::from(err)),
2251+
// break 'catch_target Try::from_error(From::from(err)),
22522252
// // Otherwise
2253-
// return Carrier::from_error(From::from(err)),
2253+
// return Try::from_error(From::from(err)),
22542254
// }
22552255

22562256
let unstable_span = self.allow_internal_unstable("?", e.span);
22572257

2258-
// Carrier::translate(<expr>)
2258+
// Try::into_result(<expr>)
22592259
let discr = {
22602260
// expand <expr>
22612261
let sub_expr = self.lower_expr(sub_expr);
22622262

2263-
let path = &["ops", "Carrier", "translate"];
2263+
let path = &["ops", "Try", "into_result"];
22642264
let path = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
22652265
P(self.expr_call(e.span, path, hir_vec![sub_expr]))
22662266
};
@@ -2306,7 +2306,7 @@ impl<'a> LoweringContext<'a> {
23062306
self.expr_call(e.span, from, hir_vec![err_expr])
23072307
};
23082308
let from_err_expr = {
2309-
let path = &["ops", "Carrier", "from_error"];
2309+
let path = &["ops", "Try", "from_error"];
23102310
let from_err = P(self.expr_std_path(unstable_span, path,
23112311
ThinVec::new()));
23122312
P(self.expr_call(e.span, from_err, hir_vec![from_expr]))

src/test/run-pass/try-operator-custom.rs

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

11-
#![feature(question_mark, question_mark_carrier)]
11+
#![feature(try_trait)]
1212

13-
use std::ops::Carrier;
13+
use std::ops::Try;
1414

1515
enum MyResult<T, U> {
1616
Awesome(T),
1717
Terrible(U)
1818
}
1919

20-
impl<U, V> Carrier for MyResult<U, V> {
21-
type Success = U;
20+
impl<U, V> Try for MyResult<U, V> {
21+
type Ok = U;
2222
type Error = V;
2323

24-
fn from_success(u: U) -> MyResult<U, V> {
24+
fn from_ok(u: U) -> MyResult<U, V> {
2525
MyResult::Awesome(u)
2626
}
2727

2828
fn from_error(e: V) -> MyResult<U, V> {
2929
MyResult::Terrible(e)
3030
}
3131

32-
fn translate<T>(self) -> T
33-
where T: Carrier<Success=U, Error=V>
34-
{
32+
fn into_result(self) -> Result<U, V> {
3533
match self {
36-
MyResult::Awesome(u) => T::from_success(u),
37-
MyResult::Terrible(e) => T::from_error(e),
34+
MyResult::Awesome(u) => Ok(u),
35+
MyResult::Terrible(e) => Err(e),
3836
}
3937
}
4038
}

0 commit comments

Comments
 (0)