Remove the Option and bool impls for carrier and add a dummy impl

The dummy impl should ensure the same type checking behaviour as having other (real) Carrier impls.
This commit is contained in:
Nick Cameron 2016-08-09 17:54:24 +12:00
parent 683bcc0295
commit 5aa89d8bf6
3 changed files with 34 additions and 77 deletions

View File

@ -76,7 +76,6 @@ use cmp::PartialOrd;
use fmt; use fmt;
use marker::{Sized, Unsize}; use marker::{Sized, Unsize};
use result::Result::{self, Ok, Err}; use result::Result::{self, Ok, Err};
use option::Option::{self, Some, None};
/// The `Drop` trait is used to run some code when a value goes out of scope. /// The `Drop` trait is used to run some code when a value goes out of scope.
/// This is sometimes called a 'destructor'. /// This is sometimes called a 'destructor'.
@ -2203,75 +2202,23 @@ impl<U, V> Carrier for Result<U, V> {
} }
} }
#[unstable(feature = "question_mark_carrier", issue = "31436")] struct _DummyErrorType;
impl<U> Carrier for Option<U> {
type Success = U;
type Error = ();
fn from_success(u: U) -> Option<U> { impl Carrier for _DummyErrorType {
Some(u)
}
fn from_error(_: ()) -> Option<U> {
None
}
fn translate<T>(self) -> T
where T: Carrier<Success=U, Error=()>
{
match self {
Some(u) => T::from_success(u),
None => T::from_error(()),
}
}
}
// Implementing Carrier for bools means it's easy to write short-circuiting
// functions. E.g.,
// ```
// fn foo() -> bool {
// if !(f() || g()) {
// return false;
// }
//
// some_computation();
// if h() {
// return false;
// }
//
// more_computation();
// i()
// }
// ```
// becomes
// ```
// fn foo() -> bool {
// (f() || g())?;
// some_computation();
// (!h())?;
// more_computation();
// i()
// }
// ```
#[unstable(feature = "question_mark_carrier", issue = "31436")]
impl Carrier for bool {
type Success = (); type Success = ();
type Error = (); type Error = ();
fn from_success(_: ()) -> bool { fn from_success(_: ()) -> _DummyErrorType {
true _DummyErrorType
} }
fn from_error(_: ()) -> bool { fn from_error(_: ()) -> _DummyErrorType {
false _DummyErrorType
} }
fn translate<T>(self) -> T fn translate<T>(self) -> T
where T: Carrier<Success=(), Error=()> where T: Carrier<Success=(), Error=()>
{ {
match self { T::from_success(())
true => T::from_success(()),
false => T::from_error(()),
}
} }
} }

View File

@ -0,0 +1,27 @@
// Copyright 2016 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(question_mark, question_mark_carrier)]
// Test that type inference fails where there are multiple possible return types
// for the `?` operator.
fn f(x: &i32) -> Result<i32, ()> {
Ok(*x)
}
fn g() -> Result<Vec<i32>, ()> {
let l = [1, 2, 3, 4];
l.iter().map(f).collect()? //~ ERROR type annotations required: cannot resolve
}
fn main() {
g();
}

View File

@ -144,23 +144,6 @@ fn merge_error() -> Result<i32, Error> {
Ok(s.parse::<i32>()? + 1) Ok(s.parse::<i32>()? + 1)
} }
fn option() -> Option<i32> {
let x = Some(42);
let y = x?;
Some(y + 2)
}
fn bool() -> bool {
let x = true;
let y = false;
let z = true;
(x || y)?;
let a: () = z?;
x?;
true
}
fn main() { fn main() {
assert_eq!(Ok(3), on_method()); assert_eq!(Ok(3), on_method());