Skip to content

Commit 27f5a6c

Browse files
committed
Switch x? desugaring to use QuestionMark trait and Try enum
1 parent fd5dc05 commit 27f5a6c

File tree

2 files changed

+78
-33
lines changed

2 files changed

+78
-33
lines changed

src/libcore/ops.rs

+53
Original file line numberDiff line numberDiff line change
@@ -2813,24 +2813,29 @@ pub trait BoxPlace<Data: ?Sized> : Place<Data> {
28132813
/// should not rely on any implementations of `Carrier` other than `Result`,
28142814
/// i.e., you should not expect `?` to continue to work with `Option`, etc.
28152815
#[unstable(feature = "question_mark_carrier", issue = "31436")]
2816+
#[cfg_attr(not(stage0), rustc_deprecated(since = "", reason = "replaced by `QuestionMark`"))]
28162817
pub trait Carrier {
28172818
/// The type of the value when computation succeeds.
28182819
type Success;
28192820
/// The type of the value when computation errors out.
28202821
type Error;
28212822

28222823
/// Create a `Carrier` from a success value.
2824+
#[allow(deprecated)]
28232825
fn from_success(Self::Success) -> Self;
28242826

28252827
/// Create a `Carrier` from an error value.
2828+
#[allow(deprecated)]
28262829
fn from_error(Self::Error) -> Self;
28272830

28282831
/// Translate this `Carrier` to another implementation of `Carrier` with the
28292832
/// same associated types.
2833+
#[allow(deprecated)]
28302834
fn translate<T>(self) -> T where T: Carrier<Success=Self::Success, Error=Self::Error>;
28312835
}
28322836

28332837
#[unstable(feature = "question_mark_carrier", issue = "31436")]
2838+
#[allow(deprecated)]
28342839
impl<U, V> Carrier for Result<U, V> {
28352840
type Success = U;
28362841
type Error = V;
@@ -2843,6 +2848,7 @@ impl<U, V> Carrier for Result<U, V> {
28432848
Err(e)
28442849
}
28452850

2851+
#[allow(deprecated)]
28462852
fn translate<T>(self) -> T
28472853
where T: Carrier<Success=U, Error=V>
28482854
{
@@ -2855,6 +2861,7 @@ impl<U, V> Carrier for Result<U, V> {
28552861

28562862
struct _DummyErrorType;
28572863

2864+
#[allow(deprecated)]
28582865
impl Carrier for _DummyErrorType {
28592866
type Success = ();
28602867
type Error = ();
@@ -2867,9 +2874,55 @@ impl Carrier for _DummyErrorType {
28672874
_DummyErrorType
28682875
}
28692876

2877+
#[allow(deprecated)]
28702878
fn translate<T>(self) -> T
28712879
where T: Carrier<Success=(), Error=()>
28722880
{
28732881
T::from_success(())
28742882
}
28752883
}
2884+
2885+
/// The `QuestionMark` trait is used to specify the functionality of `?`.
2886+
///
2887+
#[cfg(not(stage0))]
2888+
#[unstable(feature = "question_mark_qm", issue = "31436")]
2889+
pub trait QuestionMark<Done> {
2890+
///
2891+
type Continue;
2892+
///
2893+
fn question_mark(self) -> Try<Self::Continue, Done>;
2894+
}
2895+
2896+
/// The `Try` enum.
2897+
#[cfg(not(stage0))]
2898+
#[unstable(feature = "question_mark_try", issue = "31436")]
2899+
#[derive(Debug, Copy, Clone)]
2900+
pub enum Try<T, E> {
2901+
///
2902+
Continue(T),
2903+
///
2904+
Done(E),
2905+
}
2906+
2907+
#[cfg(not(stage0))]
2908+
#[unstable(feature = "question_mark_impl", issue = "31436")]
2909+
impl<T, U, E, F> QuestionMark<Result<U, F>> for Result<T, E>
2910+
where E: Into<F>
2911+
{
2912+
type Continue = T;
2913+
fn question_mark(self) -> Try<T, Result<U, F>> {
2914+
match self {
2915+
Ok(x) => Try::Continue(x),
2916+
Err(e) => Try::Done(Err(e.into())),
2917+
}
2918+
}
2919+
}
2920+
2921+
#[cfg(not(stage0))]
2922+
impl QuestionMark<_DummyErrorType> for _DummyErrorType
2923+
{
2924+
type Continue = Self;
2925+
fn question_mark(self) -> Try<Self, Self> {
2926+
Try::Continue(self)
2927+
}
2928+
}

src/librustc/hir/lowering.rs

+25-33
Original file line numberDiff line numberDiff line change
@@ -1762,56 +1762,48 @@ impl<'a> LoweringContext<'a> {
17621762
ExprKind::Try(ref sub_expr) => {
17631763
// to:
17641764
//
1765+
// match QuestionMark::question_mark(<expr>) {
1766+
// Try::Continue(val) => val,
1767+
// Try::Done(r) => return r,
1768+
// }
17651769
// match Carrier::translate(<expr>) {
17661770
// Ok(val) => val,
17671771
// Err(err) => return Carrier::from_error(From::from(err))
17681772
// }
17691773
let unstable_span = self.allow_internal_unstable("?", e.span);
17701774

1771-
// Carrier::translate(<expr>)
1775+
// QuestionMark::question_mark(<expr>)
17721776
let discr = {
17731777
// expand <expr>
17741778
let sub_expr = self.lower_expr(sub_expr);
17751779

1776-
let path = &["ops", "Carrier", "translate"];
1780+
let path = &["ops", "QuestionMark", "question_mark"];
17771781
let path = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
17781782
P(self.expr_call(e.span, path, hir_vec![sub_expr]))
17791783
};
17801784

1781-
// Ok(val) => val
1785+
// Continue(val) => val
17821786
let ok_arm = {
17831787
let val_ident = self.str_to_ident("val");
1784-
let val_pat = self.pat_ident(e.span, val_ident);
1785-
let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id));
1786-
let ok_pat = self.pat_ok(e.span, val_pat);
1788+
let val_pat = self.pat_ident(unstable_span, val_ident);
1789+
let val_expr = P(self.expr_ident(unstable_span, val_ident, val_pat.id));
1790+
let ok_pat = self.pat_continue(unstable_span, val_pat);
17871791

17881792
self.arm(hir_vec![ok_pat], val_expr)
17891793
};
17901794

1791-
// Err(err) => return Carrier::from_error(From::from(err))
1795+
// Done(r) => return r
17921796
let err_arm = {
17931797
let err_ident = self.str_to_ident("err");
1794-
let err_local = self.pat_ident(e.span, err_ident);
1795-
let from_expr = {
1796-
let path = &["convert", "From", "from"];
1797-
let from = P(self.expr_std_path(e.span, path, ThinVec::new()));
1798-
let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
1799-
1800-
self.expr_call(e.span, from, hir_vec![err_expr])
1801-
};
1802-
let from_err_expr = {
1803-
let path = &["ops", "Carrier", "from_error"];
1804-
let from_err = P(self.expr_std_path(unstable_span, path,
1805-
ThinVec::new()));
1806-
P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
1807-
};
1798+
let err_local = self.pat_ident(unstable_span, err_ident);
18081799

1809-
let ret_expr = P(self.expr(e.span,
1810-
hir::Expr_::ExprRet(Some(from_err_expr)),
1800+
let err_expr = self.expr_ident(unstable_span, err_ident, err_local.id);
1801+
let ret_expr = P(self.expr(unstable_span,
1802+
hir::Expr_::ExprRet(Some(P(err_expr))),
18111803
ThinVec::new()));
18121804

1813-
let err_pat = self.pat_err(e.span, err_local);
1814-
self.arm(hir_vec![err_pat], ret_expr)
1805+
let done_pat = self.pat_done(unstable_span, err_local);
1806+
self.arm(hir_vec![done_pat], ret_expr)
18151807
};
18161808

18171809
return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
@@ -2060,14 +2052,6 @@ impl<'a> LoweringContext<'a> {
20602052
}
20612053
}
20622054

2063-
fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2064-
self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
2065-
}
2066-
2067-
fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2068-
self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat])
2069-
}
2070-
20712055
fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
20722056
self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat])
20732057
}
@@ -2076,6 +2060,14 @@ impl<'a> LoweringContext<'a> {
20762060
self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![])
20772061
}
20782062

2063+
fn pat_continue(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2064+
self.pat_std_enum(span, &["ops", "Try", "Continue"], hir_vec![pat])
2065+
}
2066+
2067+
fn pat_done(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2068+
self.pat_std_enum(span, &["ops", "Try", "Done"], hir_vec![pat])
2069+
}
2070+
20792071
fn pat_std_enum(&mut self,
20802072
span: Span,
20812073
components: &[&str],

0 commit comments

Comments
 (0)