diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 82ba873e54b95..968d2fd7e2a47 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -404,7 +404,7 @@ pub fn char_lit(lit: &str) -> (char, isize) { .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]; @@ -413,7 +413,8 @@ pub fn char_lit(lit: &str) -> (char, isize) { .map(|x| (x, subslice.chars().count() as isize + 4)) } else { esc(6, lit) - }; + } + }; // Unicode escapes return match lit.as_bytes()[1] as char { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bf2b2c0afe6c3..d76355f9af00d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2101,10 +2101,7 @@ impl<'a> Parser<'a> { } }, 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); @@ -3000,19 +2997,30 @@ impl<'a> Parser<'a> { { 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 { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 07303ba51ff70..b58c121c5fd54 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1777,7 +1777,12 @@ impl<'a> State<'a> { 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 diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index d682ef7d70c9d..35c551931366d 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -26,7 +26,7 @@ fn main() { //~| found `Box` //~| expected () //~| found box - let _: () = (box || -> isize unimplemented!()) as Box isize>; + let _: () = (box || -> isize { unimplemented!() }) as Box isize>; //~^ ERROR mismatched types //~| expected `()` //~| found `Box isize>` diff --git a/src/test/compile-fail/liveness-issue-2163.rs b/src/test/compile-fail/liveness-issue-2163.rs index 69bceec8c3225..7c94e33b47b38 100644 --- a/src/test/compile-fail/liveness-issue-2163.rs +++ b/src/test/compile-fail/liveness-issue-2163.rs @@ -13,6 +13,6 @@ use std::vec::Vec; fn main() { let a: Vec = Vec::new(); a.iter().all(|_| -> bool { - //~^ ERROR mismatched types + //~^ ERROR not all control paths return a value }); } diff --git a/src/test/parse-fail/closure-return-syntax.rs b/src/test/parse-fail/closure-return-syntax.rs new file mode 100644 index 0000000000000..da6245597f8f4 --- /dev/null +++ b/src/test/parse-fail/closure-return-syntax.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , 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` +} diff --git a/src/test/run-pass/block-explicit-types.rs b/src/test/run-pass/block-explicit-types.rs index 54b650d762bf4..835d356d8aaa1 100644 --- a/src/test/run-pass/block-explicit-types.rs +++ b/src/test/run-pass/block-explicit-types.rs @@ -10,5 +10,5 @@ pub fn main() { fn as_buf(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) }); } diff --git a/src/test/run-pass/borrowck-move-by-capture-ok.rs b/src/test/run-pass/borrowck-move-by-capture-ok.rs index 269063bbd05b6..4364391cf0c60 100644 --- a/src/test/run-pass/borrowck-move-by-capture-ok.rs +++ b/src/test/run-pass/borrowck-move-by-capture-ok.rs @@ -14,6 +14,6 @@ pub fn main() { let bar: Box<_> = box 3; - let h = || -> int *bar; + let h = || -> int { *bar }; assert_eq!(h(), 3); } diff --git a/src/test/run-pass/issue-17816.rs b/src/test/run-pass/issue-17816.rs index a976eccf89ec4..8e3cb414566c7 100644 --- a/src/test/run-pass/issue-17816.rs +++ b/src/test/run-pass/issue-17816.rs @@ -14,7 +14,7 @@ use std::marker::PhantomData; 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![]); }