diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2014-06-01 18:41:46 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2014-06-09 20:19:07 -0700 |
| commit | f02b6f3a8bf82ca11ba50a285841fb372c4da459 (patch) | |
| tree | 4f0ae29d0f388e4570a20d22c2f6619eee464738 /src/libsyntax | |
| parent | 907d96187641d8a018af2b73239723c66b011f71 (diff) | |
| download | rust-f02b6f3a8bf82ca11ba50a285841fb372c4da459.tar.gz rust-f02b6f3a8bf82ca11ba50a285841fb372c4da459.zip | |
librustc: Implement sugar for the `FnMut` trait
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 84 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 91 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 13 |
5 files changed, 176 insertions, 29 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2bc24fd1eb3..9c3960d0f06 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -175,6 +175,7 @@ pub static DUMMY_NODE_ID: NodeId = -1; pub enum TyParamBound { TraitTyParamBound(TraitRef), StaticRegionTyParamBound, + UnboxedFnTyParamBound(UnboxedFnTy), OtherRegionTyParamBound(Span) // FIXME -- just here until work for #5723 lands } @@ -770,6 +771,11 @@ pub struct BareFnTy { } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +pub struct UnboxedFnTy { + pub decl: P<FnDecl>, +} + +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Ty_ { TyNil, TyBot, /* bottom type */ @@ -782,6 +788,7 @@ pub enum Ty_ { TyClosure(@ClosureTy, Option<Lifetime>), TyProc(@ClosureTy), TyBareFn(@BareFnTy), + TyUnboxedFn(@UnboxedFnTy), TyTup(Vec<P<Ty>> ), TyPath(Path, Option<OwnedSlice<TyParamBound>>, NodeId), // for #7264; see above TyTypeof(@Expr), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8903eb80829..03d0c283bcc 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -185,6 +185,11 @@ pub trait Folder { decl: self.fold_fn_decl(f.decl) }) } + TyUnboxedFn(ref f) => { + TyUnboxedFn(@UnboxedFnTy { + decl: self.fold_fn_decl(f.decl), + }) + } TyTup(ref tys) => TyTup(tys.iter().map(|&ty| self.fold_ty(ty)).collect()), TyPath(ref path, ref bounds, id) => { let id = self.new_id(id); @@ -440,6 +445,11 @@ fn fold_ty_param_bound<T: Folder>(tpb: &TyParamBound, fld: &mut T) match *tpb { TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)), StaticRegionTyParamBound => StaticRegionTyParamBound, + UnboxedFnTyParamBound(ref unboxed_function_type) => { + UnboxedFnTyParamBound(UnboxedFnTy { + decl: fld.fold_fn_decl(unboxed_function_type.decl), + }) + } OtherRegionTyParamBound(s) => OtherRegionTyParamBound(s) } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4af4385e3c1..360b8daa948 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -52,9 +52,9 @@ use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox}; use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyNil, TyParam, TyParamBound, TyPath, TyPtr, TyRptr}; -use ast::{TyTup, TyU32, TyUniq, TyVec, UnUniq}; -use ast::{UnnamedField, UnsafeBlock, UnsafeFn, ViewItem}; -use ast::{ViewItem_, ViewItemExternCrate, ViewItemUse}; +use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq}; +use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock}; +use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::Visibility; use ast; @@ -1058,15 +1058,27 @@ impl<'a> Parser<'a> { Vec::new() }; - let inputs = if self.eat(&token::OROR) { - Vec::new() + let (is_unboxed, inputs) = if self.eat(&token::OROR) { + (false, Vec::new()) } else { self.expect_or(); + + let is_unboxed = self.token == token::BINOP(token::AND) && + self.look_ahead(1, |t| { + token::is_keyword(keywords::Mut, t) + }) && + self.look_ahead(2, |t| *t == token::COLON); + if is_unboxed { + self.bump(); + self.bump(); + self.bump(); + } + let inputs = self.parse_seq_to_before_or( &token::COMMA, |p| p.parse_arg_general(false)); self.expect_or(); - inputs + (is_unboxed, inputs) }; let (region, bounds) = self.parse_optional_ty_param_bounds(true); @@ -1079,13 +1091,19 @@ impl<'a> Parser<'a> { variadic: false }); - TyClosure(@ClosureTy { - fn_style: fn_style, - onceness: onceness, - bounds: bounds, - decl: decl, - lifetimes: lifetimes, - }, region) + if is_unboxed { + TyUnboxedFn(@UnboxedFnTy { + decl: decl, + }) + } else { + TyClosure(@ClosureTy { + fn_style: fn_style, + onceness: onceness, + bounds: bounds, + decl: decl, + lifetimes: lifetimes, + }, region) + } } pub fn parse_unsafety(&mut self) -> FnStyle { @@ -3345,6 +3363,41 @@ impl<'a> Parser<'a> { }) } + fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy { + let inputs = if self.eat(&token::OROR) { + Vec::new() + } else { + self.expect_or(); + + if self.token == token::BINOP(token::AND) && + self.look_ahead(1, |t| { + token::is_keyword(keywords::Mut, t) + }) && + self.look_ahead(2, |t| *t == token::COLON) { + self.bump(); + self.bump(); + self.bump(); + } + + 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(); + UnboxedFnTy { + decl: P(FnDecl { + inputs: inputs, + output: output, + cf: return_style, + variadic: false, + }) + } + } + // matches optbounds = ( ( : ( boundseq )? )? ) // where boundseq = ( bound + boundseq ) | bound // and bound = 'static | ty @@ -3394,6 +3447,11 @@ impl<'a> Parser<'a> { let tref = self.parse_trait_ref(); result.push(TraitTyParamBound(tref)); } + token::BINOP(token::OR) | token::OROR => { + let unboxed_function_type = + self.parse_unboxed_function_type(); + result.push(UnboxedFnTyParamBound(unboxed_function_type)); + } _ => break, } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 05c2558da48..f22b24b5a29 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -10,7 +10,7 @@ use abi; use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound, - TraitTyParamBound, Required, Provided}; + TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided}; use ast; use ast_util; use owned_slice::OwnedSlice; @@ -505,27 +505,64 @@ impl<'a> State<'a> { lifetimes: f.lifetimes.clone(), ty_params: OwnedSlice::empty() }; - try!(self.print_ty_fn(Some(f.abi), None, &None, - f.fn_style, ast::Many, f.decl, None, &None, - Some(&generics), None)); + try!(self.print_ty_fn(Some(f.abi), + None, + &None, + f.fn_style, + ast::Many, + f.decl, + None, + &None, + Some(&generics), + None, + false)); } ast::TyClosure(f, ref region) => { let generics = ast::Generics { lifetimes: f.lifetimes.clone(), ty_params: OwnedSlice::empty() }; - try!(self.print_ty_fn(None, Some('&'), region, f.fn_style, - f.onceness, f.decl, None, &f.bounds, - Some(&generics), None)); + try!(self.print_ty_fn(None, + Some('&'), + region, + f.fn_style, + f.onceness, + f.decl, + None, + &f.bounds, + Some(&generics), + None, + false)); } ast::TyProc(f) => { let generics = ast::Generics { lifetimes: f.lifetimes.clone(), ty_params: OwnedSlice::empty() }; - try!(self.print_ty_fn(None, Some('~'), &None, f.fn_style, - f.onceness, f.decl, None, &f.bounds, - Some(&generics), None)); + try!(self.print_ty_fn(None, + Some('~'), + &None, + f.fn_style, + f.onceness, + f.decl, + None, + &f.bounds, + Some(&generics), + None, + false)); + } + ast::TyUnboxedFn(f) => { + try!(self.print_ty_fn(None, + None, + &None, + ast::NormalFn, + ast::Many, + f.decl, + None, + &None, + None, + None, + true)); } ast::TyPath(ref path, ref bounds, _) => { try!(self.print_bounded_path(path, bounds)); @@ -930,7 +967,8 @@ impl<'a> State<'a> { Some(m.ident), &None, Some(&m.generics), - Some(m.explicit_self.node))); + Some(m.explicit_self.node), + false)); word(&mut self.s, ";") } @@ -1925,6 +1963,19 @@ impl<'a> State<'a> { try!(match *bound { TraitTyParamBound(ref tref) => self.print_trait_ref(tref), StaticRegionTyParamBound => word(&mut self.s, "'static"), + UnboxedFnTyParamBound(ref unboxed_function_type) => { + self.print_ty_fn(None, + None, + &None, + ast::NormalFn, + ast::Many, + unboxed_function_type.decl, + None, + &None, + None, + None, + true) + } OtherRegionTyParamBound(_) => Ok(()) }) } @@ -2112,8 +2163,9 @@ impl<'a> State<'a> { id: Option<ast::Ident>, opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>, generics: Option<&ast::Generics>, - opt_explicit_self: Option<ast::ExplicitSelf_>) - -> IoResult<()> { + opt_explicit_self: Option<ast::ExplicitSelf_>, + is_unboxed: bool) + -> IoResult<()> { try!(self.ibox(indent_unit)); // Duplicates the logic in `print_fn_header_info()`. This is because that @@ -2129,7 +2181,9 @@ impl<'a> State<'a> { try!(self.print_fn_style(fn_style)); try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi)); try!(self.print_onceness(onceness)); - try!(word(&mut self.s, "fn")); + if !is_unboxed { + try!(word(&mut self.s, "fn")); + } } match id { @@ -2143,15 +2197,20 @@ impl<'a> State<'a> { match generics { Some(g) => try!(self.print_generics(g)), _ => () } try!(zerobreak(&mut self.s)); - if opt_sigil == Some('&') { + if is_unboxed || opt_sigil == Some('&') { try!(word(&mut self.s, "|")); } else { try!(self.popen()); } + if is_unboxed { + try!(word(&mut self.s, "&mut")); + try!(self.word_space(":")); + } + try!(self.print_fn_args(decl, opt_explicit_self)); - if opt_sigil == Some('&') { + if is_unboxed || opt_sigil == Some('&') { try!(word(&mut self.s, "|")); } else { if decl.variadic { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 906f0c16f39..b5ae8a3dea0 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -383,6 +383,12 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) { walk_lifetime_decls(visitor, &function_declaration.lifetimes, env.clone()); } + TyUnboxedFn(ref function_declaration) => { + for argument in function_declaration.decl.inputs.iter() { + visitor.visit_ty(argument.ty, env.clone()) + } + visitor.visit_ty(function_declaration.decl.output, env.clone()); + } TyPath(ref path, ref bounds, id) => { visitor.visit_path(path, id, env.clone()); for bounds in bounds.iter() { @@ -501,6 +507,13 @@ pub fn walk_ty_param_bounds<E: Clone, V: Visitor<E>>(visitor: &mut V, walk_trait_ref_helper(visitor, typ, env.clone()) } StaticRegionTyParamBound => {} + UnboxedFnTyParamBound(ref function_declaration) => { + for argument in function_declaration.decl.inputs.iter() { + visitor.visit_ty(argument.ty, env.clone()) + } + visitor.visit_ty(function_declaration.decl.output, + env.clone()); + } OtherRegionTyParamBound(..) => {} } } |
