librustc: Implement sugar for the FnMut trait
This commit is contained in:
parent
907d961876
commit
f02b6f3a8b
12 changed files with 343 additions and 46 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
@ -769,6 +770,11 @@ pub struct BareFnTy {
|
|||
pub decl: P<FnDecl>
|
||||
}
|
||||
|
||||
#[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,
|
||||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(..) => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue