diff --git a/src/doc/rust.md b/src/doc/rust.md index 96ec52c8cf9..1e1278f08bb 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -3420,8 +3420,21 @@ x = bo(5,7); ### Closure types -The type of a closure mapping an input of type `A` to an output of type `B` is `|A| -> B`. A closure with no arguments or return values has type `||`. +~~~~ {.notrust .ebnf .notation} +closure_type := [ 'unsafe' ] [ '<' lifetime-list '>' ] '|' arg-list '|' + [ ':' bound-list ] [ '->' type ] +procedure_type := 'proc' [ '<' lifetime-list '>' ] '(' arg-list ')' + [ ':' bound-list ] [ '->' type ] +lifetime-list := lifetime | lifetime ',' lifetime-list +arg-list := ident ':' type | ident ':' type ',' arg-list +bound-list := bound | bound '+' bound-list +bound := path | lifetime +~~~~ +The type of a closure mapping an input of type `A` to an output of type `B` is +`|A| -> B`. A closure with no arguments or return values has type `||`. +Similarly, a procedure mapping `A` to `B` is `proc(A) -> B` and a no-argument +and no-return value closure has type `proc()`. An example of creating and calling a closure: @@ -3444,6 +3457,30 @@ call_closure(closure_no_args, closure_args); ``` +Unlike closures, procedures may only be invoked once, but own their +environment, and are allowed to move out of their environment. Procedures are +allocated on the heap (unlike closures). An example of creating and calling a +procedure: + +```rust +let string = ~"Hello"; + +// Creates a new procedure, passing it to the `spawn` function. +spawn(proc() { + println!("{} world!", string); +}); + +// the variable `string` has been moved into the previous procedure, so it is +// no longer usable. + + +// Create an invoke a procedure. Note that the procedure is *moved* when +// invoked, so it cannot be invoked again. +let f = proc(n: int) { n + 22 }; +println!("answer: {}", f(20)); + +``` + ### Object types Every trait item (see [traits](#traits)) defines a type with the same name as the trait. diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 63b3fb09ee3..d09a002e117 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -36,8 +36,6 @@ pub enum ObsoleteSyntax { ObsoleteEnumWildcard, ObsoleteStructWildcard, ObsoleteVecDotDotWildcard, - ObsoleteBoxedClosure, - ObsoleteClosureType, ObsoleteMultipleImport, ObsoleteManagedPattern, ObsoleteManagedString, @@ -111,16 +109,6 @@ impl<'a> ParserObsoleteMethods for Parser<'a> { "vec slice wildcard", "use `..` instead of `.._` for matching slices" ), - ObsoleteBoxedClosure => ( - "managed or owned closure", - "managed closures have been removed and owned closures are \ - now written `proc()`" - ), - ObsoleteClosureType => ( - "closure type", - "closures are now written `|A| -> B` rather than `&fn(A) -> \ - B`." - ), ObsoleteMultipleImport => ( "multiple imports", "only one import is allowed per `use` statement" diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 94f5458ba53..62ce0f1e113 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -29,7 +29,7 @@ use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprVstore, ExprVstoreSlice}; use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, ExternFn, Field, FnDecl}; -use ast::{ExprVstoreUniq, Onceness, Once, Many}; +use ast::{ExprVstoreUniq, Once, Many}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod}; use ast::{Ident, ImpureFn, Inherited, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl}; @@ -892,8 +892,44 @@ impl<'a> Parser<'a> { // Parses a procedure type (`proc`). The initial `proc` keyword must // already have been parsed. pub fn parse_proc_type(&mut self) -> Ty_ { - let bounds = self.parse_optional_ty_param_bounds(); - let (decl, lifetimes) = self.parse_ty_fn_decl(false); + /* + + proc <'lt> (S) [:Bounds] -> T + ^~~^ ^~~~^ ^ ^~~~~~~~^ ^ + | | | | | + | | | | Return type + | | | Bounds + | | Argument types + | Lifetimes + the `proc` keyword + + */ + + // NOTE: remove after the next stage0 snap + let (decl, lifetimes, bounds) = if self.token == token::COLON { + let (_, bounds) = self.parse_optional_ty_param_bounds(false); + let (decl, lifetimes) = self.parse_ty_fn_decl(false); + (decl, lifetimes, bounds) + } else { + let lifetimes = if self.eat(&token::LT) { + let lifetimes = self.parse_lifetimes(); + self.expect_gt(); + lifetimes + } else { + Vec::new() + }; + + let (inputs, variadic) = self.parse_fn_args(false, false); + let (_, bounds) = self.parse_optional_ty_param_bounds(false); + let (ret_style, ret_ty) = self.parse_ret_ty(); + let decl = P(FnDecl { + inputs: inputs, + output: ret_ty, + cf: ret_style, + variadic: variadic + }); + (decl, lifetimes, bounds) + }; TyClosure(@ClosureTy { sigil: OwnedSigil, region: None, @@ -906,102 +942,68 @@ impl<'a> Parser<'a> { } // parse a TyClosure type - pub fn parse_ty_closure(&mut self, - opt_sigil: Option, - mut region: Option) - -> Ty_ { + pub fn parse_ty_closure(&mut self) -> Ty_ { /* - (&|~|@) ['r] [unsafe] [once] fn [:Bounds] <'lt> (S) -> T - ^~~~~~^ ^~~^ ^~~~~~~^ ^~~~~^ ^~~~~~~~^ ^~~~^ ^~^ ^ - | | | | | | | | - | | | | | | | Return type - | | | | | | Argument types - | | | | | Lifetimes - | | | | Closure bounds - | | | Once-ness (a.k.a., affine) - | | Purity - | Lifetime bound - Allocation type + [unsafe] [once] <'lt> |S| [:Bounds] -> T + ^~~~~~~^ ^~~~~^ ^~~~^ ^ ^~~~~~~~^ ^ + | | | | | | + | | | | | Return type + | | | | Closure bounds + | | | Argument types + | | Lifetimes + | Once-ness (a.k.a., affine) + Purity */ - // At this point, the allocation type and lifetime bound have been - // parsed. - + // NOTE: remove 'let region' after a stage0 snap + let region = self.parse_opt_lifetime(); let purity = self.parse_unsafety(); - let onceness = parse_onceness(self); + let onceness = if self.eat_keyword(keywords::Once) {Once} else {Many}; - 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(false); - (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(); + 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 { - Vec::new() - }; - - let inputs = if self.eat(&token::OROR) { - Vec::new() - } 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 = P(FnDecl { - inputs: inputs, - output: output, - cf: return_style, - variadic: false - }); - - (BorrowedSigil, decl, lifetimes, bounds) - } + lifetimes + } else { + Vec::new() }; - return TyClosure(@ClosureTy { - sigil: sigil, + let inputs = if self.eat(&token::OROR) { + Vec::new() + } 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 (new_region, bounds) = self.parse_optional_ty_param_bounds(true); + + // NOTE: this should be removed after a stage0 snap + let region = new_region.or(region); + + let (return_style, output) = self.parse_ret_ty(); + let decl = P(FnDecl { + inputs: inputs, + output: output, + cf: return_style, + variadic: false + }); + + TyClosure(@ClosureTy { + sigil: BorrowedSigil, region: region, purity: purity, onceness: onceness, bounds: bounds, decl: decl, lifetimes: lifetimes, - }); - - fn parse_onceness(this: &mut Parser) -> Onceness { - if this.eat_keyword(keywords::Once) { - Once - } else { - Many - } - } + }) } pub fn parse_unsafety(&mut self) -> Purity { @@ -1245,6 +1247,7 @@ impl<'a> Parser<'a> { self.token == token::BINOP(token::OR) || self.token == token::OROR || self.token == token::LT || + // NOTE: remove this clause after a stage0 snap Parser::token_is_lifetime(&self.token) { // CLOSURE // @@ -1252,9 +1255,7 @@ impl<'a> Parser<'a> { // 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 + self.parse_ty_closure() } else if self.eat_keyword(keywords::Typeof) { // TYPEOF // In order to not be ambiguous, the type must be surrounded by parens. @@ -1288,23 +1289,6 @@ impl<'a> Parser<'a> { pub fn parse_box_or_uniq_pointee(&mut self, sigil: ast::Sigil) -> Ty_ { - // ~'foo fn() or ~fn() are parsed directly as obsolete fn types: - match self.token { - token::LIFETIME(..) => { - let lifetime = self.parse_lifetime(); - self.obsolete(self.last_span, ObsoleteBoxedClosure); - return self.parse_ty_closure(Some(sigil), Some(lifetime)); - } - - token::IDENT(..) => { - if self.token_is_old_style_closure_keyword() { - self.obsolete(self.last_span, ObsoleteBoxedClosure); - return self.parse_ty_closure(Some(sigil), None); - } - } - _ => {} - } - // other things are parsed as @/~ + a type. Note that constructs like // ~[] and ~str will be resolved during typeck to slices and so forth, // rather than boxed ptrs. But the special casing of str/vec is not @@ -1320,11 +1304,6 @@ impl<'a> Parser<'a> { // look for `&'lt` or `&'foo ` and interpret `foo` as the region name: let opt_lifetime = self.parse_opt_lifetime(); - if self.token_is_old_style_closure_keyword() { - self.obsolete(self.last_span, ObsoleteClosureType); - return self.parse_ty_closure(Some(BorrowedSigil), opt_lifetime); - } - let mt = self.parse_mt(); return TyRptr(opt_lifetime, mt); } @@ -1540,7 +1519,8 @@ impl<'a> Parser<'a> { // Next, parse a colon and bounded type parameters, if applicable. let bounds = if mode == LifetimeAndTypesAndBounds { - self.parse_optional_ty_param_bounds() + let (_, bounds) = self.parse_optional_ty_param_bounds(false); + bounds } else { None }; @@ -3376,11 +3356,19 @@ impl<'a> Parser<'a> { // Returns "Some(Empty)" if there's a colon but nothing after (e.g. "T:") // Returns "Some(stuff)" otherwise (e.g. "T:stuff"). // NB: The None/Some distinction is important for issue #7264. - fn parse_optional_ty_param_bounds(&mut self) -> Option> { + // + // Note that the `allow_any_lifetime` argument is a hack for now while the + // AST doesn't support arbitrary lifetimes in bounds on type parameters. In + // the future, this flag should be removed, and the return value of this + // function should be Option<~[TyParamBound]> + fn parse_optional_ty_param_bounds(&mut self, allow_any_lifetime: bool) + -> (Option, Option>) + { if !self.eat(&token::COLON) { - return None; + return (None, None); } + let mut ret_lifetime = None; let mut result = vec!(); loop { match self.token { @@ -3388,6 +3376,19 @@ impl<'a> Parser<'a> { let lifetime_interned_string = token::get_ident(lifetime); if lifetime_interned_string.equiv(&("static")) { result.push(RegionTyParamBound); + if allow_any_lifetime && ret_lifetime.is_none() { + ret_lifetime = Some(ast::Lifetime { + id: ast::DUMMY_NODE_ID, + span: self.span, + name: lifetime.name + }); + } + } else if allow_any_lifetime && ret_lifetime.is_none() { + ret_lifetime = Some(ast::Lifetime { + id: ast::DUMMY_NODE_ID, + span: self.span, + name: lifetime.name + }); } else { self.span_err(self.span, "`'static` is the only permissible region bound here"); @@ -3406,13 +3407,13 @@ impl<'a> Parser<'a> { } } - return Some(OwnedSlice::from_vec(result)); + return (ret_lifetime, Some(OwnedSlice::from_vec(result))); } // matches typaram = IDENT optbounds ( EQ ty )? fn parse_ty_param(&mut self) -> TyParam { let ident = self.parse_ident(); - let opt_bounds = self.parse_optional_ty_param_bounds(); + let (_, opt_bounds) = self.parse_optional_ty_param_bounds(false); // For typarams we don't care about the difference b/w "" and "". let bounds = opt_bounds.unwrap_or_default(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index fe969c6fd51..44e95aa9573 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1557,7 +1557,7 @@ impl<'a> State<'a> { match *opt_bounds { None => Ok(()), - Some(ref bounds) => self.print_bounds(bounds, true), + Some(ref bounds) => self.print_bounds(&None, bounds, true), } } @@ -1813,11 +1813,24 @@ impl<'a> State<'a> { self.maybe_print_comment(decl.output.span.lo) } - pub fn print_bounds(&mut self, bounds: &OwnedSlice, + pub fn print_bounds(&mut self, + region: &Option, + bounds: &OwnedSlice, print_colon_anyway: bool) -> IoResult<()> { - if !bounds.is_empty() { + if !bounds.is_empty() || region.is_some() { try!(word(&mut self.s, ":")); let mut first = true; + match *region { + Some(ref lt) => { + let token = token::get_name(lt.name); + if token.get() != "static" { + try!(self.nbsp()); + first = false; + try!(self.print_lifetime(lt)); + } + } + None => {} + } for bound in bounds.iter() { try!(self.nbsp()); if first { @@ -1866,7 +1879,7 @@ impl<'a> State<'a> { let idx = idx - generics.lifetimes.len(); let param = generics.ty_params.get(idx); try!(s.print_ident(param.ident)); - try!(s.print_bounds(¶m.bounds, false)); + try!(s.print_bounds(&None, ¶m.bounds, false)); match param.default { Some(default) => { try!(space(&mut s.s)); @@ -2027,15 +2040,11 @@ impl<'a> State<'a> { try!(word(&mut self.s, "proc")); } else if opt_sigil == Some(ast::BorrowedSigil) { try!(self.print_extern_opt_abi(opt_abi)); - for lifetime in opt_region.iter() { - try!(self.print_lifetime(lifetime)); - } try!(self.print_purity(purity)); try!(self.print_onceness(onceness)); } else { try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi)); try!(self.print_opt_sigil(opt_sigil)); - try!(self.print_opt_lifetime(opt_region)); try!(self.print_purity(purity)); try!(self.print_onceness(onceness)); try!(word(&mut self.s, "fn")); @@ -2049,10 +2058,6 @@ impl<'a> State<'a> { _ => () } - if opt_sigil != Some(ast::BorrowedSigil) { - opt_bounds.as_ref().map(|bounds| self.print_bounds(bounds, true)); - } - match generics { Some(g) => try!(self.print_generics(g)), _ => () } try!(zerobreak(&mut self.s)); @@ -2066,8 +2071,6 @@ impl<'a> State<'a> { if opt_sigil == Some(ast::BorrowedSigil) { try!(word(&mut self.s, "|")); - - opt_bounds.as_ref().map(|bounds| self.print_bounds(bounds, true)); } else { if decl.variadic { try!(word(&mut self.s, ", ...")); @@ -2075,6 +2078,10 @@ impl<'a> State<'a> { try!(self.pclose()); } + opt_bounds.as_ref().map(|bounds| { + self.print_bounds(opt_region, bounds, true) + }); + try!(self.maybe_print_comment(decl.output.span.lo)); match decl.output.node { diff --git a/src/test/bench/shootout-meteor.rs b/src/test/bench/shootout-meteor.rs index 45ce1776620..ee1697e52cf 100644 --- a/src/test/bench/shootout-meteor.rs +++ b/src/test/bench/shootout-meteor.rs @@ -15,11 +15,11 @@ // returns an infinite iterator of repeated applications of f to x, // i.e. [x, f(x), f(f(x)), ...], as haskell iterate function. -fn iterate<'a, T>(x: T, f: 'a |&T| -> T) -> Iterate<'a, T> { +fn iterate<'a, T>(x: T, f: |&T|: 'a -> T) -> Iterate<'a, T> { Iterate {f: f, next: x} } struct Iterate<'a, T> { - f: 'a |&T| -> T, + f: |&T|: 'a -> T, next: T } impl<'a, T> Iterator for Iterate<'a, T> { diff --git a/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs b/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs index 1c6d65ba541..9176412cd79 100644 --- a/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs +++ b/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs @@ -12,8 +12,8 @@ fn bar(blk: ||:'static) { } fn foo(x: &()) { - bar(|| { - let _ = x; //~ ERROR does not fulfill `'static` + bar(|| { //~ ERROR cannot infer an appropriate lifetime + let _ = x; }) } diff --git a/src/test/run-pass/closure-syntax.rs b/src/test/run-pass/closure-syntax.rs new file mode 100644 index 00000000000..798808a1572 --- /dev/null +++ b/src/test/run-pass/closure-syntax.rs @@ -0,0 +1,76 @@ +// 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. + +// ignore-pretty #13324 + +#![allow(dead_code)] + +fn foo() {} + +trait Bar1 {} +impl Bar1 for proc() {} + +trait Bar2 {} +impl Bar2 for proc(): Send {} + +trait Bar3 {} +impl<'b> Bar3 for <'a>|&'a int|: 'b + Send -> &'a int {} + +trait Bar4 {} +impl Bar4 for proc<'a>(&'a int) -> &'a int {} + +struct Foo<'a> { + a: ||: 'a, + b: ||: 'static, + c: <'b>||: 'a, + d: ||: 'a + Share, + e: <'b>|int|: 'a + Share -> &'b f32, + f: proc(), + g: proc(): 'static + Share, + h: proc<'b>(int): Share -> &'b f32, +} + +fn f<'a>(a: &'a int, f: <'b>|&'b int| -> &'b int) -> &'a int { + f(a) +} + +fn g<'a>(a: &'a int, f: proc<'b>(&'b int) -> &'b int) -> &'a int { + f(a) +} + +fn bar<'b>() { + foo::<||>(); + foo::<|| -> ()>(); + foo::<||:>(); + foo::<||:'b>(); + foo::<||:'b + Share>(); + foo::<||:Share>(); + foo::< <'a>|int, f32, &'a int|:'b + Share -> &'a int>(); + foo::(); + foo:: ()>(); + foo::(); + foo::(); + foo::(); + foo::(int, f32, &'a int):'static + Share -> &'a int>(); + + // issue #11209 + let _: 'b ||; // for comparison + let _: <'a> ||; + + let _: Option<||:'b>; + // let _: Option<<'a>||>; + let _: Option< <'a>||>; + + // issue #11210 + let _: 'static ||; +} + +pub fn main() { +} diff --git a/src/test/run-pass/const-fn-val.rs b/src/test/run-pass/const-fn-val.rs index 18638ab6877..57e37aaf393 100644 --- a/src/test/run-pass/const-fn-val.rs +++ b/src/test/run-pass/const-fn-val.rs @@ -12,7 +12,7 @@ fn foo() -> int { return 0xca7f000d; } -struct Bar<'a> { f: 'a || -> int } +struct Bar<'a> { f: ||: 'a -> int } static mut b : Bar<'static> = Bar { f: foo }; diff --git a/src/test/run-pass/const-vec-of-fns.rs b/src/test/run-pass/const-vec-of-fns.rs index 9a93fcb5f89..1f5c1a556a9 100644 --- a/src/test/run-pass/const-vec-of-fns.rs +++ b/src/test/run-pass/const-vec-of-fns.rs @@ -17,7 +17,7 @@ fn f() { } static bare_fns: &'static [fn()] = &[f, f]; -struct S<'a>('a ||); +struct S<'a>(||:'a); static mut closures: &'static [S<'static>] = &[S(f), S(f)]; pub fn main() { diff --git a/src/test/run-pass/expr-block-fn.rs b/src/test/run-pass/expr-block-fn.rs index 9ca41c56dc9..3a6cd61fa09 100644 --- a/src/test/run-pass/expr-block-fn.rs +++ b/src/test/run-pass/expr-block-fn.rs @@ -11,7 +11,7 @@ fn test_fn() { - type t = 'static || -> int; + type t = ||: 'static -> int; fn ten() -> int { return 10; } let rs: t = ten; assert!((rs() == 10)); diff --git a/src/test/run-pass/expr-block-generic-box1.rs b/src/test/run-pass/expr-block-generic-box1.rs index eaead09a2f7..513dbf2eba8 100644 --- a/src/test/run-pass/expr-block-generic-box1.rs +++ b/src/test/run-pass/expr-block-generic-box1.rs @@ -10,7 +10,7 @@ #[feature(managed_boxes)]; -type compare = 'static |@T, @T| -> bool; +type compare = |@T, @T|: 'static -> bool; fn test_generic(expected: @T, eq: compare) { let actual: @T = { expected }; diff --git a/src/test/run-pass/expr-block-generic-box2.rs b/src/test/run-pass/expr-block-generic-box2.rs index 9727f41d144..5eb3f36ce1b 100644 --- a/src/test/run-pass/expr-block-generic-box2.rs +++ b/src/test/run-pass/expr-block-generic-box2.rs @@ -12,7 +12,7 @@ // ignore-fast -type compare<'a, T> = 'a |T, T| -> bool; +type compare<'a, T> = |T, T|: 'a -> bool; fn test_generic(expected: T, eq: compare) { let actual: T = { expected.clone() }; diff --git a/src/test/run-pass/expr-block-generic-unique1.rs b/src/test/run-pass/expr-block-generic-unique1.rs index b3fbd8c7658..95f3ff62d26 100644 --- a/src/test/run-pass/expr-block-generic-unique1.rs +++ b/src/test/run-pass/expr-block-generic-unique1.rs @@ -10,7 +10,7 @@ -type compare<'a, T> = 'a |~T, ~T| -> bool; +type compare<'a, T> = |~T, ~T|: 'a -> bool; fn test_generic(expected: ~T, eq: compare) { let actual: ~T = { expected.clone() }; diff --git a/src/test/run-pass/expr-block-generic-unique2.rs b/src/test/run-pass/expr-block-generic-unique2.rs index 787f50c1b03..85a1d137d21 100644 --- a/src/test/run-pass/expr-block-generic-unique2.rs +++ b/src/test/run-pass/expr-block-generic-unique2.rs @@ -10,7 +10,7 @@ // ignore-fast -type compare<'a, T> = 'a |T, T| -> bool; +type compare<'a, T> = |T, T|: 'a -> bool; fn test_generic(expected: T, eq: compare) { let actual: T = { expected.clone() }; diff --git a/src/test/run-pass/expr-block-generic.rs b/src/test/run-pass/expr-block-generic.rs index 3a1a79aa38e..4c8a32ce3cb 100644 --- a/src/test/run-pass/expr-block-generic.rs +++ b/src/test/run-pass/expr-block-generic.rs @@ -12,7 +12,7 @@ // ignore-fast // Tests for standalone blocks as expressions with dynamic type sizes -type compare<'a, T> = 'a |T, T| -> bool; +type compare<'a, T> = |T, T|: 'a -> bool; fn test_generic(expected: T, eq: compare) { let actual: T = { expected.clone() }; diff --git a/src/test/run-pass/expr-if-generic-box1.rs b/src/test/run-pass/expr-if-generic-box1.rs index cba01fbd8dd..78f42120ab7 100644 --- a/src/test/run-pass/expr-if-generic-box1.rs +++ b/src/test/run-pass/expr-if-generic-box1.rs @@ -10,7 +10,7 @@ #[feature(managed_boxes)]; -type compare = 'static |@T, @T| -> bool; +type compare = |@T, @T|: 'static -> bool; fn test_generic(expected: @T, not_expected: @T, eq: compare) { let actual: @T = if true { expected } else { not_expected }; diff --git a/src/test/run-pass/expr-if-generic-box2.rs b/src/test/run-pass/expr-if-generic-box2.rs index eba30fa9bca..8b78aabd860 100644 --- a/src/test/run-pass/expr-if-generic-box2.rs +++ b/src/test/run-pass/expr-if-generic-box2.rs @@ -12,7 +12,7 @@ // ignore-fast -type compare = 'static |T, T| -> bool; +type compare = |T, T|: 'static -> bool; fn test_generic(expected: T, not_expected: T, eq: compare) { let actual: T = if true { expected.clone() } else { not_expected }; diff --git a/src/test/run-pass/expr-if-generic.rs b/src/test/run-pass/expr-if-generic.rs index 7e58d466b90..f250db1f692 100644 --- a/src/test/run-pass/expr-if-generic.rs +++ b/src/test/run-pass/expr-if-generic.rs @@ -11,7 +11,7 @@ // ignore-fast // Tests for if as expressions with dynamic type sizes -type compare = 'static |T, T| -> bool; +type compare = |T, T|: 'static -> bool; fn test_generic(expected: T, not_expected: T, eq: compare) { let actual: T = if true { expected.clone() } else { not_expected }; diff --git a/src/test/run-pass/expr-match-generic-box1.rs b/src/test/run-pass/expr-match-generic-box1.rs index 82e80e7da7d..287e0ea349d 100644 --- a/src/test/run-pass/expr-match-generic-box1.rs +++ b/src/test/run-pass/expr-match-generic-box1.rs @@ -10,7 +10,7 @@ #[feature(managed_boxes)]; -type compare = 'static |@T, @T| -> bool; +type compare = |@T, @T|: 'static -> bool; fn test_generic(expected: @T, eq: compare) { let actual: @T = match true { true => { expected }, _ => fail!() }; diff --git a/src/test/run-pass/expr-match-generic-box2.rs b/src/test/run-pass/expr-match-generic-box2.rs index 1ad9db46257..01b46528c7b 100644 --- a/src/test/run-pass/expr-match-generic-box2.rs +++ b/src/test/run-pass/expr-match-generic-box2.rs @@ -12,7 +12,7 @@ // ignore-fast -type compare = 'static |T, T| -> bool; +type compare = |T, T|: 'static -> bool; fn test_generic(expected: T, eq: compare) { let actual: T = match true { true => { expected.clone() }, _ => fail!("wat") }; diff --git a/src/test/run-pass/expr-match-generic-unique1.rs b/src/test/run-pass/expr-match-generic-unique1.rs index af9022ed322..991a1f449f1 100644 --- a/src/test/run-pass/expr-match-generic-unique1.rs +++ b/src/test/run-pass/expr-match-generic-unique1.rs @@ -10,7 +10,7 @@ -type compare = 'static |~T, ~T| -> bool; +type compare = |~T, ~T|: 'static -> bool; fn test_generic(expected: ~T, eq: compare) { let actual: ~T = match true { diff --git a/src/test/run-pass/expr-match-generic-unique2.rs b/src/test/run-pass/expr-match-generic-unique2.rs index 97848471590..6c1a6d22de7 100644 --- a/src/test/run-pass/expr-match-generic-unique2.rs +++ b/src/test/run-pass/expr-match-generic-unique2.rs @@ -10,7 +10,7 @@ // ignore-fast -type compare<'a, T> = 'a |T, T| -> bool; +type compare<'a, T> = |T, T|: 'a -> bool; fn test_generic(expected: T, eq: compare) { let actual: T = match true { diff --git a/src/test/run-pass/fn-coerce-field.rs b/src/test/run-pass/fn-coerce-field.rs index e49b1e9ed61..6b7490ba673 100644 --- a/src/test/run-pass/fn-coerce-field.rs +++ b/src/test/run-pass/fn-coerce-field.rs @@ -9,7 +9,7 @@ // except according to those terms. struct r<'a> { - field: 'a || + field: ||: 'a, } pub fn main() { diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index a57cf3e59ae..3ff7fea95f1 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -28,7 +28,7 @@ mod map_reduce { use std::str; use std::task; - pub type putter<'a> = 'a |~str, ~str|; + pub type putter<'a> = |~str, ~str|: 'a; pub type mapper = extern fn(~str, putter); diff --git a/src/test/run-pass/issue-10767.rs b/src/test/run-pass/issue-10767.rs new file mode 100644 index 00000000000..3254f5bc35f --- /dev/null +++ b/src/test/run-pass/issue-10767.rs @@ -0,0 +1,15 @@ +// 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. + +pub fn main() { + fn f() { + }; + let _: ~fn() = ~f; +} diff --git a/src/test/run-pass/issue-3052.rs b/src/test/run-pass/issue-3052.rs index 5bd41e8bf3b..00e6b5ca8fe 100644 --- a/src/test/run-pass/issue-3052.rs +++ b/src/test/run-pass/issue-3052.rs @@ -9,7 +9,7 @@ // except according to those terms. -type Connection = 'static |Vec |; +type Connection = |Vec|: 'static; fn f() -> Option { let mock_connection: Connection = |_| {}; diff --git a/src/test/run-pass/issue-3904.rs b/src/test/run-pass/issue-3904.rs index fe6521b4df9..81a7d073c4c 100644 --- a/src/test/run-pass/issue-3904.rs +++ b/src/test/run-pass/issue-3904.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type ErrPrinter<'a> = 'a |&str, &str|; +type ErrPrinter<'a> = |&str, &str|: 'a; fn example_err(prog: &str, arg: &str) { println!("{}: {}", prog, arg) diff --git a/src/test/run-pass/issue-6157.rs b/src/test/run-pass/issue-6157.rs index 50e5f97034a..5a78aed5826 100644 --- a/src/test/run-pass/issue-6157.rs +++ b/src/test/run-pass/issue-6157.rs @@ -10,7 +10,7 @@ pub trait OpInt<'a> { fn call<'a>(&'a self, int, int) -> int; } -impl<'a> OpInt<'a> for 'a |int, int| -> int { +impl<'a> OpInt<'a> for |int, int|: 'a -> int { fn call(&self, a:int, b:int) -> int { (*self)(a, b) } diff --git a/src/test/run-pass/once-move-out-on-stack.rs b/src/test/run-pass/once-move-out-on-stack.rs index f14827c7245..995fc091113 100644 --- a/src/test/run-pass/once-move-out-on-stack.rs +++ b/src/test/run-pass/once-move-out-on-stack.rs @@ -12,7 +12,7 @@ // ignore-fast -#[feature(once_fns)]; +#![feature(once_fns)] extern crate sync; use sync::Arc; diff --git a/src/test/run-pass/regions-copy-closure.rs b/src/test/run-pass/regions-copy-closure.rs index 55cb5c62684..ac40fb885a1 100644 --- a/src/test/run-pass/regions-copy-closure.rs +++ b/src/test/run-pass/regions-copy-closure.rs @@ -9,10 +9,10 @@ // except according to those terms. struct closure_box<'a> { - cl: 'a ||, + cl: ||: 'a, } -fn box_it<'r>(x: 'r ||) -> closure_box<'r> { +fn box_it<'r>(x: ||: 'r) -> closure_box<'r> { closure_box {cl: x} } diff --git a/src/test/run-pass/regions-dependent-autofn.rs b/src/test/run-pass/regions-dependent-autofn.rs index b50930dd294..e9cd7fb4973 100644 --- a/src/test/run-pass/regions-dependent-autofn.rs +++ b/src/test/run-pass/regions-dependent-autofn.rs @@ -11,9 +11,9 @@ // Test lifetimes are linked properly when we autoslice a vector. // Issue #3148. -fn subslice<'r>(v: 'r ||) -> 'r || { v } +fn subslice<'r>(v: ||: 'r) -> ||: 'r { v } -fn both<'r>(v: 'r ||) -> 'r || { +fn both<'r>(v: ||: 'r) -> ||: 'r { subslice(subslice(v)) } diff --git a/src/test/run-pass/regions-static-closure.rs b/src/test/run-pass/regions-static-closure.rs index ff4b43cb6b5..d91c11dde10 100644 --- a/src/test/run-pass/regions-static-closure.rs +++ b/src/test/run-pass/regions-static-closure.rs @@ -9,10 +9,10 @@ // except according to those terms. struct closure_box<'a> { - cl: 'a ||, + cl: ||: 'a, } -fn box_it<'r>(x: 'r ||) -> closure_box<'r> { +fn box_it<'r>(x: ||: 'r) -> closure_box<'r> { closure_box {cl: x} }