.map(|x| (x, len as isize))
}
- let unicode_escape = || -> Option<(char, isize)>
+ let unicode_escape = || -> Option<(char, isize)> {
if lit.as_bytes()[2] == b'{' {
let idx = lit.find('}').expect(msg2);
let subslice = &lit[3..idx];
.map(|x| (x, subslice.chars().count() as isize + 4))
} else {
esc(6, lit)
- };
+ }
+ };
// Unicode escapes
return match lit.as_bytes()[1] as char {
}
},
token::OpenDelim(token::Brace) => {
- self.bump();
- let blk = self.parse_block_tail(lo, DefaultBlock);
- return self.mk_expr(blk.span.lo, blk.span.hi,
- ExprBlock(blk));
+ return self.parse_block_expr(lo, DefaultBlock);
},
token::BinOp(token::Or) | token::OrOr => {
return self.parse_lambda_expr(CaptureByRef);
{
let lo = self.span.lo;
let decl = self.parse_fn_block_decl();
- let body = self.parse_expr();
- let fakeblock = P(ast::Block {
- id: ast::DUMMY_NODE_ID,
- stmts: vec![],
- span: body.span,
- expr: Some(body),
- rules: DefaultBlock,
- });
+ let body = match decl.output {
+ DefaultReturn(_) => {
+ // If no explicit return type is given, parse any
+ // expr and wrap it up in a dummy block:
+ let body_expr = self.parse_expr();
+ P(ast::Block {
+ id: ast::DUMMY_NODE_ID,
+ stmts: vec![],
+ span: body_expr.span,
+ expr: Some(body_expr),
+ rules: DefaultBlock,
+ })
+ }
+ _ => {
+ // If an explicit return type is given, require a
+ // block to appear (RFC 968).
+ self.parse_block()
+ }
+ };
self.mk_expr(
lo,
- fakeblock.span.hi,
- ExprClosure(capture_clause, decl, fakeblock))
+ body.span.hi,
+ ExprClosure(capture_clause, decl, body))
}
pub fn parse_else_expr(&mut self) -> P<Expr> {
try!(self.print_fn_block_args(&**decl));
try!(space(&mut self.s));
- if !body.stmts.is_empty() || !body.expr.is_some() {
+ let default_return = match decl.output {
+ ast::DefaultReturn(..) => true,
+ _ => false
+ };
+
+ if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
try!(self.print_block_unclosed(&**body));
} else {
// we extract the block, so as not to create another set of boxes
//~| found `Box<core::ops::Fn(isize, isize)>`
//~| expected ()
//~| found box
- let _: () = (box || -> isize unimplemented!()) as Box<FnMut() -> isize>;
+ let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
//~^ ERROR mismatched types
//~| expected `()`
//~| found `Box<core::ops::FnMut() -> isize>`
fn main() {
let a: Vec<isize> = Vec::new();
a.iter().all(|_| -> bool {
- //~^ ERROR mismatched types
+ //~^ ERROR not all control paths return a value
});
}
--- /dev/null
+// Copyright 2014 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.
+
+// Test that we cannot parse a closure with an explicit return type
+// unless it uses braces.
+
+fn main() {
+ let x = || -> i32 22; //~ ERROR expected `{`, found `22`
+}
pub fn main() {
fn as_buf<T, F>(s: String, f: F) -> T where F: FnOnce(String) -> T { f(s) }
- as_buf("foo".to_string(), |foo: String| -> () println!("{}", foo) );
+ as_buf("foo".to_string(), |foo: String| -> () { println!("{}", foo) });
}
pub fn main() {
let bar: Box<_> = box 3;
- let h = || -> int *bar;
+ let h = || -> int { *bar };
assert_eq!(h(), 3);
}
fn main() {
struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F, marker: PhantomData<&'a ()> }
- let f = |x: Vec<&str>| -> &str "foobar";
+ let f = |x: Vec<&str>| -> &str { "foobar" };
let sym = Symbol { function: f, marker: PhantomData };
(sym.function)(vec![]);
}