diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 2f8c1f6f97d59..ab1ca420afab1 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -308,10 +308,11 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { ident: Option, sig: &ty::FnSig) -> ~str { - let mut s = ~"extern "; - - s.push_str(abis.to_str()); - s.push_char(' '); + let mut s = if abis.is_rust() { + ~"" + } else { + format!("extern {} ", abis.to_str()) + }; match purity { ast::impure_fn => {} @@ -331,16 +332,16 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { _ => { } } - push_sig_to_str(cx, &mut s, sig); + push_sig_to_str(cx, &mut s, '(', ')', sig); return s; } - fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str - { + fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str { let is_proc = (cty.sigil, cty.onceness) == (ast::OwnedSigil, ast::Once); + let is_borrowed_closure = cty.sigil == ast::BorrowedSigil; - let mut s = if is_proc { + let mut s = if is_proc || is_borrowed_closure { ~"" } else { cty.sigil.to_str() @@ -374,23 +375,42 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { } }; - s.push_str("fn"); + if !is_borrowed_closure { + s.push_str("fn"); + } } - if !cty.bounds.is_empty() { - s.push_str(":"); - } - s.push_str(cty.bounds.repr(cx)); + if !is_borrowed_closure { + // Print bounds before `fn` if this is not a borrowed closure. + if !cty.bounds.is_empty() { + s.push_str(":"); + s.push_str(cty.bounds.repr(cx)); + } + + push_sig_to_str(cx, &mut s, '(', ')', &cty.sig); + } else { + // Print bounds after the signature if this is a borrowed closure. + push_sig_to_str(cx, &mut s, '|', '|', &cty.sig); - push_sig_to_str(cx, &mut s, &cty.sig); + if is_borrowed_closure { + if !cty.bounds.is_empty() { + s.push_str(":"); + s.push_str(cty.bounds.repr(cx)); + } + } + } return s; } - fn push_sig_to_str(cx: ctxt, s: &mut ~str, sig: &ty::FnSig) { - s.push_char('('); + fn push_sig_to_str(cx: ctxt, + s: &mut ~str, + bra: char, + ket: char, + sig: &ty::FnSig) { + s.push_char(bra); let strs = sig.inputs.map(|a| fn_input_to_str(cx, *a)); s.push_str(strs.connect(", ")); - s.push_char(')'); + s.push_char(ket); if ty::get(sig.output).sty != ty_nil { s.push_str(" -> "); if ty::type_is_bot(sig.output) { diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index 8bbc4b62eb923..261792977b3a9 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -138,11 +138,118 @@ pub fn u64_from_be_bytes(data: &[u8], #[cfg(test)] mod test { - use option::{Some, None}; - use cell::Cell; + use option::{None, Option, Some}; use rt::io::mem::{MemReader, MemWriter}; - use rt::io::mock::MockReader; - use rt::io::{io_error, placeholder_error}; + use rt::io::{Reader, io_error, placeholder_error}; + + struct InitialZeroByteReader { + count: int, + } + + impl Reader for InitialZeroByteReader { + fn read(&mut self, buf: &mut [u8]) -> Option { + if self.count == 0 { + self.count = 1; + Some(0) + } else { + buf[0] = 10; + Some(1) + } + } + fn eof(&mut self) -> bool { + false + } + } + + struct EofReader; + + impl Reader for EofReader { + fn read(&mut self, _: &mut [u8]) -> Option { + None + } + fn eof(&mut self) -> bool { + false + } + } + + struct ErroringReader; + + impl Reader for ErroringReader { + fn read(&mut self, _: &mut [u8]) -> Option { + io_error::cond.raise(placeholder_error()); + None + } + fn eof(&mut self) -> bool { + false + } + } + + struct PartialReader { + count: int, + } + + impl Reader for PartialReader { + fn read(&mut self, buf: &mut [u8]) -> Option { + if self.count == 0 { + self.count = 1; + buf[0] = 10; + buf[1] = 11; + Some(2) + } else { + buf[0] = 12; + buf[1] = 13; + Some(2) + } + } + fn eof(&mut self) -> bool { + false + } + } + + struct ErroringLaterReader { + count: int, + } + + impl Reader for ErroringLaterReader { + fn read(&mut self, buf: &mut [u8]) -> Option { + if self.count == 0 { + self.count = 1; + buf[0] = 10; + Some(1) + } else { + io_error::cond.raise(placeholder_error()); + None + } + } + fn eof(&mut self) -> bool { + false + } + } + + struct ThreeChunkReader { + count: int, + } + + impl Reader for ThreeChunkReader { + fn read(&mut self, buf: &mut [u8]) -> Option { + if self.count == 0 { + self.count = 1; + buf[0] = 10; + buf[1] = 11; + Some(2) + } else if self.count == 1 { + self.count = 2; + buf[0] = 12; + buf[1] = 13; + Some(2) + } else { + None + } + } + fn eof(&mut self) -> bool { + false + } + } #[test] fn read_byte() { @@ -153,18 +260,8 @@ mod test { #[test] fn read_byte_0_bytes() { - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - Some(0) - } else { - buf[0] = 10; - Some(1) - } - } + let mut reader = InitialZeroByteReader { + count: 0, }; let byte = reader.read_byte(); assert!(byte == Some(10)); @@ -172,19 +269,14 @@ mod test { #[test] fn read_byte_eof() { - let mut reader = MockReader::new(); - reader.read = |_| None; + let mut reader = EofReader; let byte = reader.read_byte(); assert!(byte == None); } #[test] fn read_byte_error() { - let mut reader = MockReader::new(); - reader.read = |_| { - io_error::cond.raise(placeholder_error()); - None - }; + let mut reader = ErroringReader; do io_error::cond.trap(|_| { }).inside { let byte = reader.read_byte(); @@ -194,18 +286,8 @@ mod test { #[test] fn bytes_0_bytes() { - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - Some(0) - } else { - buf[0] = 10; - Some(1) - } - } + let reader = InitialZeroByteReader { + count: 0, }; let byte = reader.bytes().next(); assert!(byte == Some(10)); @@ -213,19 +295,14 @@ mod test { #[test] fn bytes_eof() { - let mut reader = MockReader::new(); - reader.read = |_| None; + let reader = EofReader; let byte = reader.bytes().next(); assert!(byte == None); } #[test] fn bytes_error() { - let mut reader = MockReader::new(); - reader.read = |_| { - io_error::cond.raise(placeholder_error()); - None - }; + let reader = ErroringReader; let mut it = reader.bytes(); do io_error::cond.trap(|_| ()).inside { let byte = it.next(); @@ -233,7 +310,6 @@ mod test { } } - #[test] fn read_bytes() { let mut reader = MemReader::new(~[10, 11, 12, 13]); @@ -243,21 +319,8 @@ mod test { #[test] fn read_bytes_partial() { - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - buf[0] = 10; - buf[1] = 11; - Some(2) - } else { - buf[0] = 12; - buf[1] = 13; - Some(2) - } - } + let mut reader = PartialReader { + count: 0, }; let bytes = reader.read_bytes(4); assert!(bytes == ~[10, 11, 12, 13]); @@ -282,21 +345,8 @@ mod test { #[test] fn push_bytes_partial() { - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - buf[0] = 10; - buf[1] = 11; - Some(2) - } else { - buf[0] = 12; - buf[1] = 13; - Some(2) - } - } + let mut reader = PartialReader { + count: 0, }; let mut buf = ~[8, 9]; reader.push_bytes(&mut buf, 4); @@ -316,19 +366,8 @@ mod test { #[test] fn push_bytes_error() { - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - buf[0] = 10; - Some(1) - } else { - io_error::cond.raise(placeholder_error()); - None - } - } + let mut reader = ErroringLaterReader { + count: 0, }; let mut buf = ~[8, 9]; do io_error::cond.trap(|_| { } ).inside { @@ -342,19 +381,8 @@ mod test { fn push_bytes_fail_reset_len() { // push_bytes unsafely sets the vector length. This is testing that // upon failure the length is reset correctly. - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - buf[0] = 10; - Some(1) - } else { - io_error::cond.raise(placeholder_error()); - None - } - } + let mut reader = ErroringLaterReader { + count: 0, }; let buf = @mut ~[8, 9]; do (|| { @@ -368,24 +396,8 @@ mod test { #[test] fn read_to_end() { - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - buf[0] = 10; - buf[1] = 11; - Some(2) - } else if *count == 1 { - *count = 2; - buf[0] = 12; - buf[1] = 13; - Some(2) - } else { - None - } - } + let mut reader = ThreeChunkReader { + count: 0, }; let buf = reader.read_to_end(); assert!(buf == ~[10, 11, 12, 13]); @@ -394,20 +406,8 @@ mod test { #[test] #[should_fail] fn read_to_end_error() { - let mut reader = MockReader::new(); - let count = Cell::new(0); - reader.read = |buf| { - do count.with_mut_ref |count| { - if *count == 0 { - *count = 1; - buf[0] = 10; - buf[1] = 11; - Some(2) - } else { - io_error::cond.raise(placeholder_error()); - None - } - } + let mut reader = ThreeChunkReader { + count: 0, }; let buf = reader.read_to_end(); assert!(buf == ~[10, 11]); diff --git a/src/libstd/rt/io/mock.rs b/src/libstd/rt/io/mock.rs deleted file mode 100644 index a0fd6846ce9b4..0000000000000 --- a/src/libstd/rt/io/mock.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 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. - -use option::{Option, None}; -use rt::io::{Reader, Writer}; - -pub struct MockReader { - read: ~fn(buf: &mut [u8]) -> Option, - priv eof: ~fn() -> bool -} - -impl MockReader { - pub fn new() -> MockReader { - MockReader { - read: |_| None, - eof: || false - } - } -} - -impl Reader for MockReader { - fn read(&mut self, buf: &mut [u8]) -> Option { (self.read)(buf) } - fn eof(&mut self) -> bool { (self.eof)() } -} - -pub struct MockWriter { - priv write: ~fn(buf: &[u8]), -} - -impl MockWriter { - pub fn new() -> MockWriter { - MockWriter { - write: |_| (), - } - } -} - -impl Writer for MockWriter { - fn write(&mut self, buf: &[u8]) { (self.write)(buf) } -} diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs index 1fd3bf1f23809..be205749186fb 100644 --- a/src/libstd/rt/io/mod.rs +++ b/src/libstd/rt/io/mod.rs @@ -323,9 +323,6 @@ pub mod native { } } -/// Mock implementations for testing -mod mock; - /// Signal handling pub mod signal; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 68796a39f1bce..56254704e28d5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -561,6 +561,45 @@ impl Parser { } } + // Expect and consume a `|`. If `||` is seen, replace it with a single + // `|` and continue. If a `|` is not seen, signal an error. + fn expect_or(&self) { + match *self.token { + token::BINOP(token::OR) => self.bump(), + token::OROR => { + self.replace_token(token::BINOP(token::OR), + self.span.lo + BytePos(1), + self.span.hi) + } + _ => { + let found_token = self.token_to_str(&token::BINOP(token::OR)); + self.fatal(format!("expected `{}`, found `{}`", + found_token, + self.this_token_to_str())) + } + } + } + + // Parse a sequence bracketed by `|` and `|`, stopping before the `|`. + fn parse_seq_to_before_or(&self, + sep: &token::Token, + f: &fn(&Parser) -> T) + -> ~[T] { + let mut first = true; + let mut vector = ~[]; + while *self.token != token::BINOP(token::OR) && + *self.token != token::OROR { + if first { + first = false + } else { + self.expect(sep) + } + + vector.push(f(self)) + } + vector + } + // expect and consume a GT. if a >> is seen, replace it // with a single > and continue. If a GT is not seen, // signal an error. @@ -761,11 +800,33 @@ impl Parser { get_ident_interner().get(id.name) } - // is this one of the keywords that signals a closure type? - pub fn token_is_closure_keyword(&self, tok: &token::Token) -> bool { - token::is_keyword(keywords::Unsafe, tok) || - token::is_keyword(keywords::Once, tok) || - token::is_keyword(keywords::Fn, tok) + // Is the current token one of the keywords that signals a bare function + // type? + pub fn token_is_bare_fn_keyword(&self) -> bool { + if token::is_keyword(keywords::Fn, self.token) { + return true + } + + if token::is_keyword(keywords::Unsafe, self.token) || + token::is_keyword(keywords::Once, self.token) { + return self.look_ahead(1, |t| token::is_keyword(keywords::Fn, t)) + } + + false + } + + // Is the current token one of the keywords that signals a closure type? + pub fn token_is_closure_keyword(&self) -> bool { + token::is_keyword(keywords::Unsafe, self.token) || + token::is_keyword(keywords::Once, self.token) + } + + // Is the current token one of the keywords that signals an old-style + // closure type (with explicit sigil)? + pub fn token_is_old_style_closure_keyword(&self) -> bool { + token::is_keyword(keywords::Unsafe, self.token) || + token::is_keyword(keywords::Once, self.token) || + token::is_keyword(keywords::Fn, self.token) } pub fn token_is_lifetime(&self, tok: &token::Token) -> bool { @@ -786,15 +847,15 @@ impl Parser { pub fn parse_ty_bare_fn(&self) -> ty_ { /* - extern "ABI" [unsafe] fn <'lt> (S) -> T - ^~~~^ ^~~~~~~^ ^~~~^ ^~^ ^ - | | | | | - | | | | Return type - | | | Argument types - | | Lifetimes - | | - | Purity - ABI + [extern "ABI"] [unsafe] fn <'lt> (S) -> T + ^~~~^ ^~~~~~~^ ^~~~^ ^~^ ^ + | | | | | + | | | | Return type + | | | Argument types + | | Lifetimes + | | + | Purity + ABI */ @@ -828,8 +889,8 @@ impl Parser { // parse a ty_closure type pub fn parse_ty_closure(&self, - sigil: ast::Sigil, - region: Option) + opt_sigil: Option, + mut region: Option) -> ty_ { /* @@ -852,10 +913,58 @@ impl Parser { let purity = self.parse_unsafety(); let onceness = parse_onceness(self); - self.expect_keyword(keywords::Fn); - let bounds = self.parse_optional_ty_param_bounds(); - let (decl, lifetimes) = self.parse_ty_fn_decl(); + let (sigil, decl, lifetimes, bounds) = match opt_sigil { + Some(sigil) => { + // Old-style closure syntax (`fn(A)->B`). + self.expect_keyword(keywords::Fn); + let bounds = self.parse_optional_ty_param_bounds(); + let (decl, lifetimes) = self.parse_ty_fn_decl(); + (sigil, decl, lifetimes, bounds) + } + None => { + // New-style closure syntax (`<'lt>|A|:K -> B`). + let lifetimes = if self.eat(&token::LT) { + let lifetimes = self.parse_lifetimes(); + self.expect_gt(); + + // Re-parse the region here. What a hack. + if region.is_some() { + self.span_err(*self.last_span, + "lifetime declarations must precede \ + the lifetime associated with a \ + closure"); + } + region = self.parse_opt_lifetime(); + + lifetimes + } else { + opt_vec::Empty + }; + + let inputs = if self.eat(&token::OROR) { + ~[] + } else { + self.expect_or(); + let inputs = self.parse_seq_to_before_or( + &token::COMMA, + |p| p.parse_arg_general(false)); + self.expect_or(); + inputs + }; + + let bounds = self.parse_optional_ty_param_bounds(); + + let (return_style, output) = self.parse_ret_ty(); + let decl = ast::fn_decl { + inputs: inputs, + output: output, + cf: return_style, + }; + + (BorrowedSigil, decl, lifetimes, bounds) + } + }; return ty_closure(@TyClosure { sigil: sigil, @@ -1120,13 +1229,23 @@ impl Parser { // BORROWED POINTER self.bump(); self.parse_borrowed_pointee() - } else if self.eat_keyword(keywords::Extern) { - // EXTERN FUNCTION + } else if self.is_keyword(keywords::Extern) || + self.token_is_bare_fn_keyword() { + // BARE FUNCTION self.parse_ty_bare_fn() - } else if self.token_is_closure_keyword(self.token) { + } else if self.token_is_closure_keyword() || + *self.token == token::BINOP(token::OR) || + *self.token == token::OROR || + *self.token == token::LT || + self.token_is_lifetime(self.token) { // CLOSURE - let result = self.parse_ty_closure(ast::BorrowedSigil, None); - self.obsolete(*self.last_span, ObsoleteBareFnType); + // + // XXX(pcwalton): Eventually `token::LT` will not unambiguously + // introduce a closure, once procs can have lifetime bounds. We + // will need to refactor the grammar a little bit at that point. + + let lifetime = self.parse_opt_lifetime(); + let result = self.parse_ty_closure(None, lifetime); result } else if self.eat_keyword(keywords::Typeof) { // TYPEOF @@ -1161,12 +1280,12 @@ impl Parser { match *self.token { token::LIFETIME(*) => { let lifetime = self.parse_lifetime(); - return self.parse_ty_closure(sigil, Some(lifetime)); + return self.parse_ty_closure(Some(sigil), Some(lifetime)); } token::IDENT(*) => { - if self.token_is_closure_keyword(self.token) { - return self.parse_ty_closure(sigil, None); + if self.token_is_old_style_closure_keyword() { + return self.parse_ty_closure(Some(sigil), None); } } _ => {} @@ -1187,8 +1306,8 @@ impl Parser { // look for `&'lt` or `&'foo ` and interpret `foo` as the region name: let opt_lifetime = self.parse_opt_lifetime(); - if self.token_is_closure_keyword(self.token) { - return self.parse_ty_closure(BorrowedSigil, opt_lifetime); + if self.token_is_old_style_closure_keyword() { + return self.parse_ty_closure(Some(BorrowedSigil), opt_lifetime); } let mt = self.parse_mt(); @@ -4390,8 +4509,13 @@ impl Parser { } } - // parse a string as an ABI spec on an extern type or module + // Parses a string as an ABI spec on an extern type or module. Consumes + // the `extern` keyword, if one is found. fn parse_opt_abis(&self) -> Option { + if !self.eat_keyword(keywords::Extern) { + return None + } + match *self.token { token::LIT_STR(s) | token::LIT_STR_RAW(s, _) => { @@ -4467,7 +4591,7 @@ impl Parser { }); } // either a view item or an item: - if self.eat_keyword(keywords::Extern) { + if self.is_keyword(keywords::Extern) { let opt_abis = self.parse_opt_abis(); if self.eat_keyword(keywords::Fn) { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 33bdcdd1b0305..0eb1045efe95f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2015,20 +2015,39 @@ pub fn print_ty_fn(s: @ps, // function prints the sigil in the wrong place. That should be fixed. if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once { word(s.s, "proc"); - } else { + } else if opt_sigil == Some(ast::BorrowedSigil) { print_extern_opt_abis(s, opt_abis); + for lifetime in opt_region.iter() { + print_lifetime(s, lifetime); + } + print_purity(s, purity); + print_onceness(s, onceness); + } else { + print_opt_abis_and_extern_if_nondefault(s, opt_abis); print_opt_sigil(s, opt_sigil); print_opt_lifetime(s, opt_region); print_purity(s, purity); print_onceness(s, onceness); word(s.s, "fn"); } + match id { Some(id) => { word(s.s, " "); print_ident(s, id); } _ => () } - do opt_bounds.as_ref().map |bounds| { print_bounds(s, bounds, true); }; + + if opt_sigil != Some(ast::BorrowedSigil) { + do opt_bounds.as_ref().map |bounds| { + print_bounds(s, bounds, true); + }; + } + match generics { Some(g) => print_generics(s, g), _ => () } zerobreak(s.s); - popen(s); + if opt_sigil == Some(ast::BorrowedSigil) { + word(s.s, "|"); + } else { + popen(s); + } + // It is unfortunate to duplicate the commasep logic, but we want the // self type and the args all in the same box. box(s, 0u, inconsistent); @@ -2041,7 +2060,14 @@ pub fn print_ty_fn(s: @ps, print_arg(s, arg); } end(s); - pclose(s); + + if opt_sigil == Some(ast::BorrowedSigil) { + word(s.s, "|"); + + opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true)); + } else { + pclose(s); + } maybe_print_comment(s, decl.output.span.lo); @@ -2274,6 +2300,17 @@ pub fn print_opt_purity(s: @ps, opt_purity: Option) { } } +pub fn print_opt_abis_and_extern_if_nondefault(s: @ps, + opt_abis: Option) { + match opt_abis { + Some(abis) if !abis.is_rust() => { + word_nbsp(s, "extern"); + word_nbsp(s, abis.to_str()); + } + Some(_) | None => {} + }; +} + pub fn print_extern_opt_abis(s: @ps, opt_abis: Option) { match opt_abis { Some(abis) => { diff --git a/src/test/compile-fail/block-coerce-no-2.rs b/src/test/compile-fail/block-coerce-no-2.rs index 85ef09cc2a631..3e38ce9ab358b 100644 --- a/src/test/compile-fail/block-coerce-no-2.rs +++ b/src/test/compile-fail/block-coerce-no-2.rs @@ -19,5 +19,5 @@ fn main() { } f(g); - //~^ ERROR mismatched types: expected `extern "Rust" fn(extern "Rust" fn(extern "Rust" fn()))` + //~^ ERROR mismatched types: expected `fn(fn(fn()))` } diff --git a/src/test/compile-fail/closure-reform-bad.rs b/src/test/compile-fail/closure-reform-bad.rs new file mode 100644 index 0000000000000..3da709942e0e6 --- /dev/null +++ b/src/test/compile-fail/closure-reform-bad.rs @@ -0,0 +1,13 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +fn call_bare(f: fn(&str)) { + f("Hello "); +} + +fn main() { + let string = "world!"; + let f: |&str| = |s| println(s + string); + call_bare(f) //~ ERROR mismatched types +} + diff --git a/src/test/pretty/closure-reform-pretty.rs b/src/test/pretty/closure-reform-pretty.rs new file mode 100644 index 0000000000000..5169652a6c069 --- /dev/null +++ b/src/test/pretty/closure-reform-pretty.rs @@ -0,0 +1,17 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ + +// pp-exact + +fn call_it(f: proc(~str) -> ~str) { } + +fn call_this(f: |&str|: Send) { } + +fn call_that(f: <'a>|&'a int, &'a int|: -> int) { } + +fn call_extern(f: fn() -> int) { } + +fn call_abid_extern(f: extern "C" fn() -> int) { } + +pub fn main() { } + diff --git a/src/test/pretty/disamb-stmt-expr.rs b/src/test/pretty/disamb-stmt-expr.rs index f6787fa9c3d21..d3d6f1c0e355b 100644 --- a/src/test/pretty/disamb-stmt-expr.rs +++ b/src/test/pretty/disamb-stmt-expr.rs @@ -14,7 +14,7 @@ // preserved. They are needed to disambiguate `{return n+1}; - 0` from // `({return n+1}-0)`. -fn id(f: &fn() -> int) -> int { f() } +fn id(f: || -> int) -> int { f() } fn wsucc(_n: int) -> int { (do id || { 1 }) - 0 } fn main() { } diff --git a/src/test/pretty/do1.rs b/src/test/pretty/do1.rs index 751aedb39a3a8..1fb2359da53ac 100644 --- a/src/test/pretty/do1.rs +++ b/src/test/pretty/do1.rs @@ -10,6 +10,6 @@ // pp-exact -fn f(f: &fn(int)) { f(10) } +fn f(f: |int|) { f(10) } fn main() { do f |i| { assert!(i == 10) } } diff --git a/src/test/pretty/fn-types.rs b/src/test/pretty/fn-types.rs index b000c9f9137ae..27e56fb6074a1 100644 --- a/src/test/pretty/fn-types.rs +++ b/src/test/pretty/fn-types.rs @@ -10,7 +10,7 @@ // pp-exact -fn from_foreign_fn(_x: extern "Rust" fn()) { } -fn from_stack_closure(_x: &fn()) { } +fn from_foreign_fn(_x: fn()) { } +fn from_stack_closure(_x: ||) { } fn from_unique_closure(_x: ~fn()) { } fn main() { } diff --git a/src/test/run-pass/closure-reform.rs b/src/test/run-pass/closure-reform.rs index c765ebe9643bc..18ca64d0f2762 100644 --- a/src/test/run-pass/closure-reform.rs +++ b/src/test/run-pass/closure-reform.rs @@ -1,11 +1,42 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +use std::cast; + fn call_it(f: proc(~str) -> ~str) { println(f(~"Fred")) } +fn call_a_thunk(f: ||) { + f(); +} + +fn call_this(f: |&str|:Send) { + f("Hello!"); +} + +fn call_that(f: <'a>|&'a int, &'a int|: -> int) { + let (ten, forty_two) = (10, 42); + println!("Your lucky number is {}", f(&ten, &forty_two)); +} + +fn call_cramped(f:||->uint,g:<'a>||->&'a uint) { + let number = f(); + let other_number = *g(); + println!("Ticket {} wins an all-expenses-paid trip to Mountain View", number + other_number); +} + +fn call_bare(f: fn(&str)) { + f("Hello world!") +} + +fn call_bare_again(f: extern "Rust" fn(&str)) { + f("Goodbye world!") +} + pub fn main() { + // Procs + let greeting = ~"Hi "; do call_it |s| { greeting + s @@ -23,5 +54,26 @@ pub fn main() { call_it(proc(s: ~str) -> ~str { greeting + s }); + + // Closures + + call_a_thunk(|| println("Hello world!")); + + call_this(|s| println(s)); + + call_that(|x, y| *x + *y); + + let z = 100; + call_that(|x, y| *x + *y - z); + + call_cramped(|| 1, || unsafe { + cast::transmute(&100) + }); + + // External functions + + call_bare(println); + + call_bare_again(println); }