diff options
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 223 |
2 files changed, 112 insertions, 123 deletions
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<ast::Sigil>, - mut region: Option<ast::Lifetime>) - -> 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 (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(); - - // 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(); + let onceness = if self.eat_keyword(keywords::Once) {Once} else {Many}; - lifetimes - } else { - Vec::new() - }; + let lifetimes = if self.eat(&token::LT) { + let lifetimes = self.parse_lifetimes(); + self.expect_gt(); - 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 - }; + lifetimes + } else { + Vec::new() + }; - let bounds = self.parse_optional_ty_param_bounds(); + 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 (return_style, output) = self.parse_ret_ty(); - let decl = P(FnDecl { - inputs: inputs, - output: output, - cf: return_style, - variadic: false - }); + let (new_region, bounds) = self.parse_optional_ty_param_bounds(true); - (BorrowedSigil, decl, lifetimes, bounds) - } - }; + // 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 + }); - return TyClosure(@ClosureTy { - sigil: sigil, + 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<OwnedSlice<TyParamBound>> { + // + // 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<ast::Lifetime>, Option<OwnedSlice<TyParamBound>>) + { 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 "<T>" and "<T:>". let bounds = opt_bounds.unwrap_or_default(); |
