|  | //! Checks the functionality of the `?` operator in various syntactic contexts. | 
|  |  | 
|  | //@ run-pass | 
|  |  | 
|  | #![allow(dead_code)] | 
|  |  | 
|  | use std::fs::File; | 
|  | use std::io::{self, Read}; | 
|  | use std::num::ParseIntError; | 
|  | use std::str::FromStr; | 
|  |  | 
|  | fn on_method() -> Result<i32, ParseIntError> { | 
|  | Ok("1".parse::<i32>()? + "2".parse::<i32>()?) | 
|  | } | 
|  |  | 
|  | fn in_chain() -> Result<String, ParseIntError> { | 
|  | Ok("3".parse::<i32>()?.to_string()) | 
|  | } | 
|  |  | 
|  | fn on_call() -> Result<i32, ParseIntError> { | 
|  | fn parse<T: FromStr>(s: &str) -> Result<T, T::Err> { | 
|  | s.parse() | 
|  | } | 
|  |  | 
|  | Ok(parse("4")?) | 
|  | } | 
|  |  | 
|  | fn nested() -> Result<i32, ParseIntError> { | 
|  | Ok("5".parse::<i32>()?.to_string().parse()?) | 
|  | } | 
|  |  | 
|  | fn on_path() -> Result<i32, ParseIntError> { | 
|  | let x = "6".parse::<i32>(); | 
|  |  | 
|  | Ok(x?) | 
|  | } | 
|  |  | 
|  | fn on_macro() -> Result<i32, ParseIntError> { | 
|  | macro_rules! id { | 
|  | ($e:expr) => { | 
|  | $e | 
|  | }; | 
|  | } | 
|  |  | 
|  | Ok(id!("7".parse::<i32>())?) | 
|  | } | 
|  |  | 
|  | fn on_parens() -> Result<i32, ParseIntError> { | 
|  | let x = "8".parse::<i32>(); | 
|  |  | 
|  | Ok((x)?) | 
|  | } | 
|  |  | 
|  | fn on_block() -> Result<i32, ParseIntError> { | 
|  | let x = "9".parse::<i32>(); | 
|  |  | 
|  | Ok({ x }?) | 
|  | } | 
|  |  | 
|  | fn on_field() -> Result<i32, ParseIntError> { | 
|  | struct Pair<A, B> { | 
|  | a: A, | 
|  | b: B, | 
|  | } | 
|  |  | 
|  | let x = Pair { a: "10".parse::<i32>(), b: 0 }; | 
|  |  | 
|  | Ok(x.a?) | 
|  | } | 
|  |  | 
|  | fn on_tuple_field() -> Result<i32, ParseIntError> { | 
|  | let x = ("11".parse::<i32>(), 0); | 
|  |  | 
|  | Ok(x.0?) | 
|  | } | 
|  |  | 
|  | fn on_try() -> Result<i32, ParseIntError> { | 
|  | let x = "12".parse::<i32>().map(|i| i.to_string().parse::<i32>()); | 
|  |  | 
|  | Ok(x??) | 
|  | } | 
|  |  | 
|  | fn on_binary_op() -> Result<i32, ParseIntError> { | 
|  | let x = 13 - "14".parse::<i32>()?; | 
|  | let y = "15".parse::<i32>()? - 16; | 
|  | let z = "17".parse::<i32>()? - "18".parse::<i32>()?; | 
|  |  | 
|  | Ok(x + y + z) | 
|  | } | 
|  |  | 
|  | fn on_index() -> Result<i32, ParseIntError> { | 
|  | let x = [19]; | 
|  | let y = "0".parse::<usize>(); | 
|  |  | 
|  | Ok(x[y?]) | 
|  | } | 
|  |  | 
|  | fn on_args() -> Result<i32, ParseIntError> { | 
|  | fn sub(x: i32, y: i32) -> i32 { | 
|  | x - y | 
|  | } | 
|  |  | 
|  | let x = "20".parse(); | 
|  | let y = "21".parse(); | 
|  |  | 
|  | Ok(sub(x?, y?)) | 
|  | } | 
|  |  | 
|  | fn on_if() -> Result<i32, ParseIntError> { | 
|  | Ok(if true { "22".parse::<i32>() } else { "23".parse::<i32>() }?) | 
|  | } | 
|  |  | 
|  | fn on_if_let() -> Result<i32, ParseIntError> { | 
|  | Ok(if let Ok(..) = "24".parse::<i32>() { "25".parse::<i32>() } else { "26".parse::<i32>() }?) | 
|  | } | 
|  |  | 
|  | fn on_match() -> Result<i32, ParseIntError> { | 
|  | Ok(match "27".parse::<i32>() { | 
|  | Err(..) => "28".parse::<i32>(), | 
|  | Ok(..) => "29".parse::<i32>(), | 
|  | }?) | 
|  | } | 
|  |  | 
|  | fn tight_binding() -> Result<bool, ()> { | 
|  | fn ok<T>(x: T) -> Result<T, ()> { | 
|  | Ok(x) | 
|  | } | 
|  |  | 
|  | let x = ok(true); | 
|  | Ok(!x?) | 
|  | } | 
|  |  | 
|  | // just type check | 
|  | fn merge_error() -> Result<i32, Error> { | 
|  | let mut s = String::new(); | 
|  |  | 
|  | File::open("foo.txt")?.read_to_string(&mut s)?; | 
|  |  | 
|  | Ok(s.parse::<i32>()? + 1) | 
|  | } | 
|  |  | 
|  | fn main() { | 
|  | assert_eq!(Ok(3), on_method()); | 
|  |  | 
|  | assert_eq!(Ok("3".to_string()), in_chain()); | 
|  |  | 
|  | assert_eq!(Ok(4), on_call()); | 
|  |  | 
|  | assert_eq!(Ok(5), nested()); | 
|  |  | 
|  | assert_eq!(Ok(6), on_path()); | 
|  |  | 
|  | assert_eq!(Ok(7), on_macro()); | 
|  |  | 
|  | assert_eq!(Ok(8), on_parens()); | 
|  |  | 
|  | assert_eq!(Ok(9), on_block()); | 
|  |  | 
|  | assert_eq!(Ok(10), on_field()); | 
|  |  | 
|  | assert_eq!(Ok(11), on_tuple_field()); | 
|  |  | 
|  | assert_eq!(Ok(12), on_try()); | 
|  |  | 
|  | assert_eq!(Ok(-3), on_binary_op()); | 
|  |  | 
|  | assert_eq!(Ok(19), on_index()); | 
|  |  | 
|  | assert_eq!(Ok(-1), on_args()); | 
|  |  | 
|  | assert_eq!(Ok(22), on_if()); | 
|  |  | 
|  | assert_eq!(Ok(25), on_if_let()); | 
|  |  | 
|  | assert_eq!(Ok(29), on_match()); | 
|  |  | 
|  | assert_eq!(Ok(false), tight_binding()); | 
|  | } | 
|  |  | 
|  | enum Error { | 
|  | Io(io::Error), | 
|  | Parse(ParseIntError), | 
|  | } | 
|  |  | 
|  | impl From<io::Error> for Error { | 
|  | fn from(e: io::Error) -> Error { | 
|  | Error::Io(e) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<ParseIntError> for Error { | 
|  | fn from(e: ParseIntError) -> Error { | 
|  | Error::Parse(e) | 
|  | } | 
|  | } |