1
Fork 0

Generalize and abstract ThinAttributes

This commit is contained in:
Jeffrey Seyfried 2016-06-18 04:01:57 +00:00
parent 114be1e9f0
commit 5033eca65f
27 changed files with 278 additions and 317 deletions

View file

@ -14,7 +14,6 @@
use hir::*; use hir::*;
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem}; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem};
use syntax::ast::MetaItemKind; use syntax::ast::MetaItemKind;
use syntax::attr::ThinAttributesExt;
use hir; use hir;
use syntax::codemap::{respan, Span, Spanned}; use syntax::codemap::{respan, Span, Spanned};
use syntax::ptr::P; use syntax::ptr::P;
@ -292,8 +291,11 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
}) })
} }
pub fn fold_attrs<T: Folder>(attrs: HirVec<Attribute>, fld: &mut T) -> HirVec<Attribute> { pub fn fold_attrs<T, F>(attrs: T, fld: &mut F) -> T
attrs.move_flat_map(|x| fld.fold_attribute(x)) where T: Into<Vec<Attribute>> + From<Vec<Attribute>>,
F: Folder,
{
attrs.into().move_flat_map(|x| fld.fold_attribute(x)).into()
} }
pub fn noop_fold_arm<T: Folder>(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm { pub fn noop_fold_arm<T: Folder>(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm {
@ -461,7 +463,7 @@ pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
pat: fld.fold_pat(pat), pat: fld.fold_pat(pat),
init: init.map(|e| fld.fold_expr(e)), init: init.map(|e| fld.fold_expr(e)),
span: fld.new_span(span), span: fld.new_span(span),
attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs.into(), fld).into()), attrs: fold_attrs(attrs, fld),
} }
}) })
} }
@ -1078,7 +1080,7 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
} }
}, },
span: folder.new_span(span), span: folder.new_span(span),
attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs.into(), folder).into()), attrs: fold_attrs(attrs, folder),
} }
} }

View file

@ -27,7 +27,6 @@
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute}; use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
use syntax::attr::ThinAttributesExt;
use syntax::codemap::{Span, Spanned}; use syntax::codemap::{Span, Spanned};
use hir::*; use hir::*;
@ -756,7 +755,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
walk_list!(visitor, visit_arm, arms); walk_list!(visitor, visit_arm, arms);
} }
ExprClosure(_, ref function_declaration, ref body, _fn_decl_span) => { ExprClosure(_, ref function_declaration, ref body, _fn_decl_span) => {
visitor.visit_fn(FnKind::Closure(expression.attrs.as_attr_slice()), visitor.visit_fn(FnKind::Closure(&expression.attrs),
function_declaration, function_declaration,
body, body,
expression.span, expression.span,

View file

@ -50,7 +50,6 @@ use session::Session;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::iter; use std::iter;
use syntax::ast::*; use syntax::ast::*;
use syntax::attr::{ThinAttributes, ThinAttributesExt};
use syntax::ptr::P; use syntax::ptr::P;
use syntax::codemap::{respan, Spanned, Span}; use syntax::codemap::{respan, Spanned, Span};
use syntax::parse::token; use syntax::parse::token;
@ -962,16 +961,16 @@ impl<'a> LoweringContext<'a> {
let make_call = |this: &mut LoweringContext, p, args| { let make_call = |this: &mut LoweringContext, p, args| {
let path = this.core_path(e.span, p); let path = this.core_path(e.span, p);
let path = this.expr_path(path, None); let path = this.expr_path(path, ThinVec::new());
this.expr_call(e.span, path, args, None) this.expr_call(e.span, path, args)
}; };
let mk_stmt_let = |this: &mut LoweringContext, bind, expr| { let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
this.stmt_let(e.span, false, bind, expr, None) this.stmt_let(e.span, false, bind, expr)
}; };
let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| { let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
this.stmt_let(e.span, true, bind, expr, None) this.stmt_let(e.span, true, bind, expr)
}; };
// let placer = <placer_expr> ; // let placer = <placer_expr> ;
@ -980,21 +979,21 @@ impl<'a> LoweringContext<'a> {
placer_expr, placer_expr,
e.span, e.span,
hir::PopUnstableBlock, hir::PopUnstableBlock,
None); ThinVec::new());
mk_stmt_let(self, placer_ident, placer_expr) mk_stmt_let(self, placer_ident, placer_expr)
}; };
// let mut place = Placer::make_place(placer); // let mut place = Placer::make_place(placer);
let (s2, place_binding) = { let (s2, place_binding) = {
let placer = self.expr_ident(e.span, placer_ident, None, placer_binding); let placer = self.expr_ident(e.span, placer_ident, placer_binding);
let call = make_call(self, &make_place, hir_vec![placer]); let call = make_call(self, &make_place, hir_vec![placer]);
mk_stmt_let_mut(self, place_ident, call) mk_stmt_let_mut(self, place_ident, call)
}; };
// let p_ptr = Place::pointer(&mut place); // let p_ptr = Place::pointer(&mut place);
let (s3, p_ptr_binding) = { let (s3, p_ptr_binding) = {
let agent = self.expr_ident(e.span, place_ident, None, place_binding); let agent = self.expr_ident(e.span, place_ident, place_binding);
let args = hir_vec![self.expr_mut_addr_of(e.span, agent, None)]; let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
let call = make_call(self, &place_pointer, args); let call = make_call(self, &place_pointer, args);
mk_stmt_let(self, p_ptr_ident, call) mk_stmt_let(self, p_ptr_ident, call)
}; };
@ -1005,11 +1004,12 @@ impl<'a> LoweringContext<'a> {
value_expr, value_expr,
e.span, e.span,
hir::PopUnstableBlock, hir::PopUnstableBlock,
None); ThinVec::new());
self.signal_block_expr(hir_vec![], self.signal_block_expr(hir_vec![],
value_expr, value_expr,
e.span, e.span,
hir::PopUnsafeBlock(hir::CompilerGenerated), None) hir::PopUnsafeBlock(hir::CompilerGenerated),
ThinVec::new())
}; };
// push_unsafe!({ // push_unsafe!({
@ -1017,19 +1017,20 @@ impl<'a> LoweringContext<'a> {
// InPlace::finalize(place) // InPlace::finalize(place)
// }) // })
let expr = { let expr = {
let ptr = self.expr_ident(e.span, p_ptr_ident, None, p_ptr_binding); let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
let call_move_val_init = let call_move_val_init =
hir::StmtSemi( hir::StmtSemi(
make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
self.next_id()); self.next_id());
let call_move_val_init = respan(e.span, call_move_val_init); let call_move_val_init = respan(e.span, call_move_val_init);
let place = self.expr_ident(e.span, place_ident, None, place_binding); let place = self.expr_ident(e.span, place_ident, place_binding);
let call = make_call(self, &inplace_finalize, hir_vec![place]); let call = make_call(self, &inplace_finalize, hir_vec![place]);
self.signal_block_expr(hir_vec![call_move_val_init], self.signal_block_expr(hir_vec![call_move_val_init],
call, call,
e.span, e.span,
hir::PushUnsafeBlock(hir::CompilerGenerated), None) hir::PushUnsafeBlock(hir::CompilerGenerated),
ThinVec::new())
}; };
return self.signal_block_expr(hir_vec![s1, s2, s3], return self.signal_block_expr(hir_vec![s1, s2, s3],
@ -1101,7 +1102,7 @@ impl<'a> LoweringContext<'a> {
rules: hir::DefaultBlock, rules: hir::DefaultBlock,
span: span, span: span,
}); });
self.expr_block(blk, None) self.expr_block(blk, ThinVec::new())
} }
_ => self.lower_expr(els), _ => self.lower_expr(els),
} }
@ -1168,7 +1169,7 @@ impl<'a> LoweringContext<'a> {
expr, expr,
e.span, e.span,
hir::PopUnstableBlock, hir::PopUnstableBlock,
None); ThinVec::new());
this.field(token::intern(s), signal_block, ast_expr.span) this.field(token::intern(s), signal_block, ast_expr.span)
}).collect(); }).collect();
let attrs = ast_expr.attrs.clone(); let attrs = ast_expr.attrs.clone();
@ -1180,7 +1181,7 @@ impl<'a> LoweringContext<'a> {
hir_expr, hir_expr,
ast_expr.span, ast_expr.span,
hir::PushUnstableBlock, hir::PushUnstableBlock,
None) ThinVec::new())
} }
use syntax::ast::RangeLimits::*; use syntax::ast::RangeLimits::*;
@ -1267,9 +1268,9 @@ impl<'a> LoweringContext<'a> {
ex.span = e.span; ex.span = e.span;
} }
// merge attributes into the inner expression. // merge attributes into the inner expression.
ex.attrs.update(|attrs| { let mut attrs = e.attrs.clone();
attrs.prepend(e.attrs.clone()) attrs.extend::<Vec<_>>(ex.attrs.into());
}); ex.attrs = attrs;
ex ex
}); });
} }
@ -1288,7 +1289,7 @@ impl<'a> LoweringContext<'a> {
// `<pat> => <body>` // `<pat> => <body>`
let pat_arm = { let pat_arm = {
let body = self.lower_block(body); let body = self.lower_block(body);
let body_expr = self.expr_block(body, None); let body_expr = self.expr_block(body, ThinVec::new());
let pat = self.lower_pat(pat); let pat = self.lower_pat(pat);
self.arm(hir_vec![pat], body_expr) self.arm(hir_vec![pat], body_expr)
}; };
@ -1308,7 +1309,7 @@ impl<'a> LoweringContext<'a> {
attrs: hir_vec![], attrs: hir_vec![],
pats: hir_vec![pat_under], pats: hir_vec![pat_under],
guard: Some(cond), guard: Some(cond),
body: self.expr_block(then, None), body: self.expr_block(then, ThinVec::new()),
}); });
else_opt.map(|else_opt| (else_opt, true)) else_opt.map(|else_opt| (else_opt, true))
} }
@ -1339,7 +1340,7 @@ impl<'a> LoweringContext<'a> {
let else_arm = { let else_arm = {
let pat_under = self.pat_wild(e.span); let pat_under = self.pat_wild(e.span);
let else_expr = let else_expr =
else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![], None)); else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![]));
self.arm(hir_vec![pat_under], else_expr) self.arm(hir_vec![pat_under], else_expr)
}; };
@ -1374,7 +1375,7 @@ impl<'a> LoweringContext<'a> {
// `<pat> => <body>` // `<pat> => <body>`
let pat_arm = { let pat_arm = {
let body = self.lower_block(body); let body = self.lower_block(body);
let body_expr = self.expr_block(body, None); let body_expr = self.expr_block(body, ThinVec::new());
let pat = self.lower_pat(pat); let pat = self.lower_pat(pat);
self.arm(hir_vec![pat], body_expr) self.arm(hir_vec![pat], body_expr)
}; };
@ -1382,7 +1383,7 @@ impl<'a> LoweringContext<'a> {
// `_ => break` // `_ => break`
let break_arm = { let break_arm = {
let pat_under = self.pat_wild(e.span); let pat_under = self.pat_wild(e.span);
let break_expr = self.expr_break(e.span, None); let break_expr = self.expr_break(e.span, ThinVec::new());
self.arm(hir_vec![pat_under], break_expr) self.arm(hir_vec![pat_under], break_expr)
}; };
@ -1393,7 +1394,7 @@ impl<'a> LoweringContext<'a> {
hir::ExprMatch(sub_expr, hir::ExprMatch(sub_expr,
arms, arms,
hir::MatchSource::WhileLetDesugar), hir::MatchSource::WhileLetDesugar),
None); ThinVec::new());
// `[opt_ident]: loop { ... }` // `[opt_ident]: loop { ... }`
let loop_block = self.block_expr(match_expr); let loop_block = self.block_expr(match_expr);
@ -1435,7 +1436,7 @@ impl<'a> LoweringContext<'a> {
id: self.next_id(), id: self.next_id(),
node: hir::ExprBlock(body_block), node: hir::ExprBlock(body_block),
span: body_span, span: body_span,
attrs: None, attrs: ThinVec::new(),
}); });
let pat = self.lower_pat(pat); let pat = self.lower_pat(pat);
let some_pat = self.pat_some(e.span, pat); let some_pat = self.pat_some(e.span, pat);
@ -1445,7 +1446,7 @@ impl<'a> LoweringContext<'a> {
// `::std::option::Option::None => break` // `::std::option::Option::None => break`
let break_arm = { let break_arm = {
let break_expr = self.expr_break(e.span, None); let break_expr = self.expr_break(e.span, ThinVec::new());
let pat = self.pat_none(e.span); let pat = self.pat_none(e.span);
self.arm(hir_vec![pat], break_expr) self.arm(hir_vec![pat], break_expr)
}; };
@ -1461,25 +1462,26 @@ impl<'a> LoweringContext<'a> {
self.path_global(e.span, strs) self.path_global(e.span, strs)
}; };
let iter = self.expr_ident(e.span, iter, None, iter_pat.id); let iter = self.expr_ident(e.span, iter, iter_pat.id);
let ref_mut_iter = self.expr_mut_addr_of(e.span, iter, None); let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
let next_path = self.expr_path(next_path, None); let next_path = self.expr_path(next_path, ThinVec::new());
let next_expr = self.expr_call(e.span, let next_expr = self.expr_call(e.span, next_path, hir_vec![ref_mut_iter]);
next_path,
hir_vec![ref_mut_iter],
None);
let arms = hir_vec![pat_arm, break_arm]; let arms = hir_vec![pat_arm, break_arm];
self.expr(e.span, self.expr(e.span,
hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar),
None) ThinVec::new())
}; };
// `[opt_ident]: loop { ... }` // `[opt_ident]: loop { ... }`
let loop_block = self.block_expr(match_expr); let loop_block = self.block_expr(match_expr);
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident)); let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
let loop_expr = let loop_expr = P(hir::Expr {
P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None }); id: e.id,
node: loop_expr,
span: e.span,
attrs: ThinVec::new(),
});
// `mut iter => { ... }` // `mut iter => { ... }`
let iter_arm = self.arm(hir_vec![iter_pat], loop_expr); let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
@ -1492,23 +1494,22 @@ impl<'a> LoweringContext<'a> {
self.path_global(e.span, strs) self.path_global(e.span, strs)
}; };
let into_iter = self.expr_path(into_iter_path, None); let into_iter = self.expr_path(into_iter_path, ThinVec::new());
self.expr_call(e.span, into_iter, hir_vec![head], None) self.expr_call(e.span, into_iter, hir_vec![head])
}; };
let match_expr = self.expr_match(e.span, let match_expr = self.expr_match(e.span,
into_iter_expr, into_iter_expr,
hir_vec![iter_arm], hir_vec![iter_arm],
hir::MatchSource::ForLoopDesugar, hir::MatchSource::ForLoopDesugar);
None);
// `{ let _result = ...; _result }` // `{ let _result = ...; _result }`
// underscore prevents an unused_variables lint if the head diverges // underscore prevents an unused_variables lint if the head diverges
let result_ident = self.str_to_ident("_result"); let result_ident = self.str_to_ident("_result");
let (let_stmt, let_stmt_binding) = let (let_stmt, let_stmt_binding) =
self.stmt_let(e.span, false, result_ident, match_expr, None); self.stmt_let(e.span, false, result_ident, match_expr);
let result = self.expr_ident(e.span, result_ident, None, let_stmt_binding); let result = self.expr_ident(e.span, result_ident, let_stmt_binding);
let block = self.block_all(e.span, hir_vec![let_stmt], Some(result)); let block = self.block_all(e.span, hir_vec![let_stmt], Some(result));
// add the attributes to the outer returned expr node // add the attributes to the outer returned expr node
return self.expr_block(block, e.attrs.clone()); return self.expr_block(block, e.attrs.clone());
@ -1535,7 +1536,7 @@ impl<'a> LoweringContext<'a> {
let ok_arm = { let ok_arm = {
let val_ident = self.str_to_ident("val"); let val_ident = self.str_to_ident("val");
let val_pat = self.pat_ident(e.span, val_ident); let val_pat = self.pat_ident(e.span, val_ident);
let val_expr = self.expr_ident(e.span, val_ident, None, val_pat.id); let val_expr = self.expr_ident(e.span, val_ident, val_pat.id);
let ok_pat = self.pat_ok(e.span, val_pat); let ok_pat = self.pat_ok(e.span, val_pat);
self.arm(hir_vec![ok_pat], val_expr) self.arm(hir_vec![ok_pat], val_expr)
@ -1548,26 +1549,26 @@ impl<'a> LoweringContext<'a> {
let from_expr = { let from_expr = {
let path = self.std_path(&["convert", "From", "from"]); let path = self.std_path(&["convert", "From", "from"]);
let path = self.path_global(e.span, path); let path = self.path_global(e.span, path);
let from = self.expr_path(path, None); let from = self.expr_path(path, ThinVec::new());
let err_expr = self.expr_ident(e.span, err_ident, None, err_local.id); let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
self.expr_call(e.span, from, hir_vec![err_expr], None) self.expr_call(e.span, from, hir_vec![err_expr])
}; };
let err_expr = { let err_expr = {
let path = self.std_path(&["result", "Result", "Err"]); let path = self.std_path(&["result", "Result", "Err"]);
let path = self.path_global(e.span, path); let path = self.path_global(e.span, path);
let err_ctor = self.expr_path(path, None); let err_ctor = self.expr_path(path, ThinVec::new());
self.expr_call(e.span, err_ctor, hir_vec![from_expr], None) self.expr_call(e.span, err_ctor, hir_vec![from_expr])
}; };
let err_pat = self.pat_err(e.span, err_local); let err_pat = self.pat_err(e.span, err_local);
let ret_expr = self.expr(e.span, let ret_expr = self.expr(e.span,
hir::Expr_::ExprRet(Some(err_expr)), None); hir::Expr_::ExprRet(Some(err_expr)),
ThinVec::new());
self.arm(hir_vec![err_pat], ret_expr) self.arm(hir_vec![err_pat], ret_expr)
}; };
return self.expr_match(e.span, sub_expr, hir_vec![err_arm, ok_arm], return self.expr_match(e.span, sub_expr, hir_vec![err_arm, ok_arm],
hir::MatchSource::TryDesugar, None); hir::MatchSource::TryDesugar);
} }
ExprKind::Mac(_) => panic!("Shouldn't exist here"), ExprKind::Mac(_) => panic!("Shouldn't exist here"),
@ -1682,23 +1683,18 @@ impl<'a> LoweringContext<'a> {
} }
} }
fn expr_break(&mut self, span: Span, attrs: ThinAttributes) -> P<hir::Expr> { fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
self.expr(span, hir::ExprBreak(None), attrs) self.expr(span, hir::ExprBreak(None), attrs)
} }
fn expr_call(&mut self, fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<P<hir::Expr>>)
span: Span,
e: P<hir::Expr>,
args: hir::HirVec<P<hir::Expr>>,
attrs: ThinAttributes)
-> P<hir::Expr> { -> P<hir::Expr> {
self.expr(span, hir::ExprCall(e, args), attrs) self.expr(span, hir::ExprCall(e, args), ThinVec::new())
} }
fn expr_ident(&mut self, span: Span, id: Name, attrs: ThinAttributes, binding: NodeId) fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> P<hir::Expr> {
-> P<hir::Expr> {
let expr_path = hir::ExprPath(None, self.path_ident(span, id)); let expr_path = hir::ExprPath(None, self.path_ident(span, id));
let expr = self.expr(span, expr_path, attrs); let expr = self.expr(span, expr_path, ThinVec::new());
let def = self.resolver.definitions().map(|defs| { let def = self.resolver.definitions().map(|defs| {
Def::Local(defs.local_def_id(binding), binding) Def::Local(defs.local_def_id(binding), binding)
@ -1708,12 +1704,11 @@ impl<'a> LoweringContext<'a> {
expr expr
} }
fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>, attrs: ThinAttributes) fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> P<hir::Expr> {
-> P<hir::Expr> { self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), attrs)
} }
fn expr_path(&mut self, path: hir::Path, attrs: ThinAttributes) -> P<hir::Expr> { fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
let def = self.resolver.resolve_generated_global_path(&path, true); let def = self.resolver.resolve_generated_global_path(&path, true);
let expr = self.expr(path.span, hir::ExprPath(None, path), attrs); let expr = self.expr(path.span, hir::ExprPath(None, path), attrs);
self.resolver.record_resolution(expr.id, def); self.resolver.record_resolution(expr.id, def);
@ -1724,19 +1719,17 @@ impl<'a> LoweringContext<'a> {
span: Span, span: Span,
arg: P<hir::Expr>, arg: P<hir::Expr>,
arms: hir::HirVec<hir::Arm>, arms: hir::HirVec<hir::Arm>,
source: hir::MatchSource, source: hir::MatchSource)
attrs: ThinAttributes)
-> P<hir::Expr> { -> P<hir::Expr> {
self.expr(span, hir::ExprMatch(arg, arms, source), attrs) self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
} }
fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinAttributes) -> P<hir::Expr> { fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
self.expr(b.span, hir::ExprBlock(b), attrs) self.expr(b.span, hir::ExprBlock(b), attrs)
} }
fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<P<hir::Expr>>, attrs: ThinAttributes) fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<P<hir::Expr>>) -> P<hir::Expr> {
-> P<hir::Expr> { self.expr(sp, hir::ExprTup(exprs), ThinVec::new())
self.expr(sp, hir::ExprTup(exprs), attrs)
} }
fn expr_struct(&mut self, fn expr_struct(&mut self,
@ -1744,14 +1737,14 @@ impl<'a> LoweringContext<'a> {
path: hir::Path, path: hir::Path,
fields: hir::HirVec<hir::Field>, fields: hir::HirVec<hir::Field>,
e: Option<P<hir::Expr>>, e: Option<P<hir::Expr>>,
attrs: ThinAttributes) -> P<hir::Expr> { attrs: ThinVec<Attribute>) -> P<hir::Expr> {
let def = self.resolver.resolve_generated_global_path(&path, false); let def = self.resolver.resolve_generated_global_path(&path, false);
let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs); let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs);
self.resolver.record_resolution(expr.id, def); self.resolver.record_resolution(expr.id, def);
expr expr
} }
fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinAttributes) -> P<hir::Expr> { fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
P(hir::Expr { P(hir::Expr {
id: self.next_id(), id: self.next_id(),
node: node, node: node,
@ -1760,12 +1753,7 @@ impl<'a> LoweringContext<'a> {
}) })
} }
fn stmt_let(&mut self, fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
sp: Span,
mutbl: bool,
ident: Name,
ex: P<hir::Expr>,
attrs: ThinAttributes)
-> (hir::Stmt, NodeId) { -> (hir::Stmt, NodeId) {
let pat = if mutbl { let pat = if mutbl {
self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable)) self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable))
@ -1779,7 +1767,7 @@ impl<'a> LoweringContext<'a> {
init: Some(ex), init: Some(ex),
id: self.next_id(), id: self.next_id(),
span: sp, span: sp,
attrs: attrs, attrs: ThinVec::new(),
}); });
let decl = respan(sp, hir::DeclLocal(local)); let decl = respan(sp, hir::DeclLocal(local));
(respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id) (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
@ -1939,7 +1927,7 @@ impl<'a> LoweringContext<'a> {
expr: P<hir::Expr>, expr: P<hir::Expr>,
span: Span, span: Span,
rule: hir::BlockCheckMode, rule: hir::BlockCheckMode,
attrs: ThinAttributes) attrs: ThinVec<Attribute>)
-> P<hir::Expr> { -> P<hir::Expr> {
let id = self.next_id(); let id = self.next_id();
let block = P(hir::Block { let block = P(hir::Block {

View file

@ -27,7 +27,6 @@ use hir::map::{self, Node};
use syntax::abi; use syntax::abi;
use hir::{Block, FnDecl}; use hir::{Block, FnDecl};
use syntax::ast::{Attribute, Name, NodeId}; use syntax::ast::{Attribute, Name, NodeId};
use syntax::attr::ThinAttributesExt;
use hir as ast; use hir as ast;
use syntax::codemap::Span; use syntax::codemap::Span;
use hir::intravisit::FnKind; use hir::intravisit::FnKind;
@ -257,11 +256,7 @@ impl<'a> FnLikeNode<'a> {
} }
map::NodeExpr(e) => match e.node { map::NodeExpr(e) => match e.node {
ast::ExprClosure(_, ref decl, ref block, _fn_decl_span) => ast::ExprClosure(_, ref decl, ref block, _fn_decl_span) =>
closure(ClosureParts::new(&decl, closure(ClosureParts::new(&decl, &block, e.id, e.span, &e.attrs)),
&block,
e.id,
e.span,
e.attrs.as_attr_slice())),
_ => bug!("expr FnLikeNode that is not fn-like"), _ => bug!("expr FnLikeNode that is not fn-like"),
}, },
_ => bug!("other FnLikeNode that is not fn-like"), _ => bug!("other FnLikeNode that is not fn-like"),

View file

@ -23,7 +23,6 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, }; use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
use syntax::attr::ThinAttributesExt;
use syntax::codemap::{Span, Spanned}; use syntax::codemap::{Span, Spanned};
use syntax::visit; use syntax::visit;
@ -577,7 +576,7 @@ impl<'ast> Map<'ast> {
Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]), Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]), Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]), Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
Some(NodeExpr(ref e)) => Some(e.attrs.as_attr_slice()), Some(NodeExpr(ref e)) => Some(&*e.attrs),
Some(NodeStmt(ref s)) => Some(s.node.attrs()), Some(NodeStmt(ref s)) => Some(s.node.attrs()),
// unit/tuple structs take the attributes straight from // unit/tuple structs take the attributes straight from
// the struct definition. // the struct definition.

View file

@ -40,9 +40,9 @@ use syntax::codemap::{self, mk_sp, respan, Span, Spanned, ExpnId};
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect}; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
use syntax::attr::{ThinAttributes, ThinAttributesExt};
use syntax::parse::token::{keywords, InternedString}; use syntax::parse::token::{keywords, InternedString};
use syntax::ptr::P; use syntax::ptr::P;
use syntax::util::ThinVec;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt; use std::fmt;
@ -732,7 +732,7 @@ impl Stmt_ {
match *self { match *self {
StmtDecl(ref d, _) => d.node.attrs(), StmtDecl(ref d, _) => d.node.attrs(),
StmtExpr(ref e, _) | StmtExpr(ref e, _) |
StmtSemi(ref e, _) => e.attrs.as_attr_slice(), StmtSemi(ref e, _) => &e.attrs,
} }
} }
@ -756,7 +756,7 @@ pub struct Local {
pub init: Option<P<Expr>>, pub init: Option<P<Expr>>,
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
pub attrs: ThinAttributes, pub attrs: ThinVec<Attribute>,
} }
pub type Decl = Spanned<Decl_>; pub type Decl = Spanned<Decl_>;
@ -772,7 +772,7 @@ pub enum Decl_ {
impl Decl_ { impl Decl_ {
pub fn attrs(&self) -> &[Attribute] { pub fn attrs(&self) -> &[Attribute] {
match *self { match *self {
DeclLocal(ref l) => l.attrs.as_attr_slice(), DeclLocal(ref l) => &l.attrs,
DeclItem(_) => &[] DeclItem(_) => &[]
} }
} }
@ -817,7 +817,7 @@ pub struct Expr {
pub id: NodeId, pub id: NodeId,
pub node: Expr_, pub node: Expr_,
pub span: Span, pub span: Span,
pub attrs: ThinAttributes, pub attrs: ThinVec<Attribute>,
} }
impl fmt::Debug for Expr { impl fmt::Debug for Expr {

View file

@ -44,7 +44,6 @@ use syntax::codemap::Span;
use syntax::errors::DiagnosticBuilder; use syntax::errors::DiagnosticBuilder;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use syntax::ast; use syntax::ast;
use syntax::attr::ThinAttributesExt;
use hir; use hir;
use hir::intravisit as hir_visit; use hir::intravisit as hir_visit;
use hir::intravisit::{IdVisitor, IdVisitingOperation}; use hir::intravisit::{IdVisitor, IdVisitingOperation};
@ -767,7 +766,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
} }
fn visit_expr(&mut self, e: &hir::Expr) { fn visit_expr(&mut self, e: &hir::Expr) {
self.with_lint_attrs(e.attrs.as_attr_slice(), |cx| { self.with_lint_attrs(&e.attrs, |cx| {
run_lints!(cx, check_expr, late_passes, e); run_lints!(cx, check_expr, late_passes, e);
hir_visit::walk_expr(cx, e); hir_visit::walk_expr(cx, e);
}) })
@ -832,7 +831,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
} }
fn visit_local(&mut self, l: &hir::Local) { fn visit_local(&mut self, l: &hir::Local) {
self.with_lint_attrs(l.attrs.as_attr_slice(), |cx| { self.with_lint_attrs(&l.attrs, |cx| {
run_lints!(cx, check_local, late_passes, l); run_lints!(cx, check_local, late_passes, l);
hir_visit::walk_local(cx, l); hir_visit::walk_local(cx, l);
}) })
@ -928,7 +927,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
} }
fn visit_expr(&mut self, e: &ast::Expr) { fn visit_expr(&mut self, e: &ast::Expr) {
self.with_lint_attrs(e.attrs.as_attr_slice(), |cx| { self.with_lint_attrs(&e.attrs, |cx| {
run_lints!(cx, check_expr, early_passes, e); run_lints!(cx, check_expr, early_passes, e);
ast_visit::walk_expr(cx, e); ast_visit::walk_expr(cx, e);
}) })
@ -988,7 +987,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
} }
fn visit_local(&mut self, l: &ast::Local) { fn visit_local(&mut self, l: &ast::Local) {
self.with_lint_attrs(l.attrs.as_attr_slice(), |cx| { self.with_lint_attrs(&l.attrs, |cx| {
run_lints!(cx, check_local, early_passes, l); run_lints!(cx, check_local, early_passes, l);
ast_visit::walk_local(cx, l); ast_visit::walk_local(cx, l);
}) })

View file

@ -451,7 +451,7 @@ fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
id: 0, id: 0,
node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })), node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
span: DUMMY_SP, span: DUMMY_SP,
attrs: None, attrs: ast::ThinVec::new(),
}) })
} }

View file

@ -672,7 +672,7 @@ impl fold::Folder for ReplaceBodyWithLoop {
node: ast::ExprKind::Loop(empty_block, None), node: ast::ExprKind::Loop(empty_block, None),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: codemap::DUMMY_SP, span: codemap::DUMMY_SP,
attrs: None, attrs: ast::ThinVec::new(),
}); });
expr_to_block(b.rules, Some(loop_expr)) expr_to_block(b.rules, Some(loop_expr))

View file

@ -14,8 +14,9 @@ pub use self::TyParamBound::*;
pub use self::UnsafeSource::*; pub use self::UnsafeSource::*;
pub use self::ViewPath_::*; pub use self::ViewPath_::*;
pub use self::PathParameters::*; pub use self::PathParameters::*;
pub use util::ThinVec;
use attr::{ThinAttributes, HasAttrs}; use attr::HasAttrs;
use codemap::{mk_sp, respan, Span, Spanned, DUMMY_SP, ExpnId}; use codemap::{mk_sp, respan, Span, Spanned, DUMMY_SP, ExpnId};
use abi::Abi; use abi::Abi;
use errors; use errors;
@ -809,7 +810,7 @@ pub enum StmtKind {
/// Expr with trailing semi-colon (may have any type): /// Expr with trailing semi-colon (may have any type):
Semi(P<Expr>, NodeId), Semi(P<Expr>, NodeId),
Mac(P<Mac>, MacStmtStyle, ThinAttributes), Mac(P<Mac>, MacStmtStyle, ThinVec<Attribute>),
} }
impl StmtKind { impl StmtKind {
@ -851,7 +852,7 @@ pub struct Local {
pub init: Option<P<Expr>>, pub init: Option<P<Expr>>,
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
pub attrs: ThinAttributes, pub attrs: ThinVec<Attribute>,
} }
impl Local { impl Local {
@ -912,7 +913,7 @@ pub struct Expr {
pub id: NodeId, pub id: NodeId,
pub node: ExprKind, pub node: ExprKind,
pub span: Span, pub span: Span,
pub attrs: ThinAttributes pub attrs: ThinVec<Attribute>
} }
impl Expr { impl Expr {

View file

@ -26,6 +26,7 @@ use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use parse::token::InternedString; use parse::token::InternedString;
use parse::{ParseSess, token}; use parse::{ParseSess, token};
use ptr::P; use ptr::P;
use util::ThinVec;
use std::cell::{RefCell, Cell}; use std::cell::{RefCell, Cell};
use std::collections::HashSet; use std::collections::HashSet;
@ -803,80 +804,6 @@ impl IntType {
} }
} }
/// A list of attributes, behind a optional box as
/// a space optimization.
pub type ThinAttributes = Option<Box<Vec<Attribute>>>;
pub trait ThinAttributesExt {
fn map_thin_attrs<F>(self, f: F) -> Self
where F: FnOnce(Vec<Attribute>) -> Vec<Attribute>;
fn prepend(mut self, attrs: Self) -> Self;
fn append(mut self, attrs: Self) -> Self;
fn update<F>(&mut self, f: F)
where Self: Sized,
F: FnOnce(Self) -> Self;
fn as_attr_slice(&self) -> &[Attribute];
fn into_attr_vec(self) -> Vec<Attribute>;
}
impl ThinAttributesExt for ThinAttributes {
fn map_thin_attrs<F>(self, f: F) -> Self
where F: FnOnce(Vec<Attribute>) -> Vec<Attribute>
{
f(self.map(|b| *b).unwrap_or(Vec::new())).into_thin_attrs()
}
fn prepend(self, attrs: ThinAttributes) -> Self {
attrs.map_thin_attrs(|mut attrs| {
attrs.extend(self.into_attr_vec());
attrs
})
}
fn append(self, attrs: ThinAttributes) -> Self {
self.map_thin_attrs(|mut self_| {
self_.extend(attrs.into_attr_vec());
self_
})
}
fn update<F>(&mut self, f: F)
where Self: Sized,
F: FnOnce(ThinAttributes) -> ThinAttributes
{
let self_ = f(self.take());
*self = self_;
}
fn as_attr_slice(&self) -> &[Attribute] {
match *self {
Some(ref b) => b,
None => &[],
}
}
fn into_attr_vec(self) -> Vec<Attribute> {
match self {
Some(b) => *b,
None => Vec::new(),
}
}
}
pub trait AttributesExt {
fn into_thin_attrs(self) -> ThinAttributes;
}
impl AttributesExt for Vec<Attribute> {
fn into_thin_attrs(self) -> ThinAttributes {
if self.len() == 0 {
None
} else {
Some(Box::new(self))
}
}
}
pub trait HasAttrs: Sized { pub trait HasAttrs: Sized {
fn attrs(&self) -> &[ast::Attribute]; fn attrs(&self) -> &[ast::Attribute];
fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self; fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self;
@ -885,13 +812,13 @@ pub trait HasAttrs: Sized {
/// A cheap way to add Attributes to an AST node. /// A cheap way to add Attributes to an AST node.
pub trait WithAttrs { pub trait WithAttrs {
// FIXME: Could be extended to anything IntoIter<Item=Attribute> // FIXME: Could be extended to anything IntoIter<Item=Attribute>
fn with_attrs(self, attrs: ThinAttributes) -> Self; fn with_attrs(self, attrs: ThinVec<Attribute>) -> Self;
} }
impl<T: HasAttrs> WithAttrs for T { impl<T: HasAttrs> WithAttrs for T {
fn with_attrs(self, attrs: ThinAttributes) -> Self { fn with_attrs(self, attrs: ThinVec<Attribute>) -> Self {
self.map_attrs(|mut orig_attrs| { self.map_attrs(|mut orig_attrs| {
orig_attrs.extend(attrs.into_attr_vec()); orig_attrs.extend::<Vec<_>>(attrs.into());
orig_attrs orig_attrs
}) })
} }
@ -906,12 +833,12 @@ impl HasAttrs for Vec<Attribute> {
} }
} }
impl HasAttrs for ThinAttributes { impl HasAttrs for ThinVec<Attribute> {
fn attrs(&self) -> &[Attribute] { fn attrs(&self) -> &[Attribute] {
self.as_attr_slice() &self
} }
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
self.map_thin_attrs(f) f(self.into()).into()
} }
} }

View file

@ -350,7 +350,7 @@ impl DummyResult {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Lit(P(codemap::respan(sp, ast::LitKind::Bool(false)))), node: ast::ExprKind::Lit(P(codemap::respan(sp, ast::LitKind::Bool(false)))),
span: sp, span: sp,
attrs: None, attrs: ast::ThinVec::new(),
}) })
} }

View file

@ -525,7 +525,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
init: Some(ex), init: Some(ex),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: sp, span: sp,
attrs: None, attrs: ast::ThinVec::new(),
}); });
let decl = respan(sp, ast::DeclKind::Local(local)); let decl = respan(sp, ast::DeclKind::Local(local));
respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)) respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))
@ -550,7 +550,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
init: Some(ex), init: Some(ex),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: sp, span: sp,
attrs: None, attrs: ast::ThinVec::new(),
}); });
let decl = respan(sp, ast::DeclKind::Local(local)); let decl = respan(sp, ast::DeclKind::Local(local));
P(respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))) P(respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)))
@ -587,7 +587,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: node, node: node,
span: span, span: span,
attrs: None, attrs: ast::ThinVec::new(),
}) })
} }

View file

@ -16,7 +16,7 @@ use ast;
use ext::mtwt; use ext::mtwt;
use ext::build::AstBuilder; use ext::build::AstBuilder;
use attr; use attr;
use attr::{AttrMetaMethods, WithAttrs, ThinAttributesExt}; use attr::{AttrMetaMethods, WithAttrs};
use codemap; use codemap;
use codemap::{Span, Spanned, ExpnInfo, ExpnId, NameAndSpan, MacroBang, MacroAttribute}; use codemap::{Span, Spanned, ExpnInfo, ExpnId, NameAndSpan, MacroBang, MacroAttribute};
use config::StripUnconfigured; use config::StripUnconfigured;
@ -104,7 +104,7 @@ pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
// expr_mac should really be expr_ext or something; it's the // expr_mac should really be expr_ext or something; it's the
// entry-point for all syntax extensions. // entry-point for all syntax extensions.
ast::ExprKind::Mac(mac) => { ast::ExprKind::Mac(mac) => {
expand_mac_invoc(mac, None, expr.attrs.into_attr_vec(), expr.span, fld) expand_mac_invoc(mac, None, expr.attrs.into(), expr.span, fld)
} }
ast::ExprKind::While(cond, body, opt_ident) => { ast::ExprKind::While(cond, body, opt_ident) => {
@ -449,7 +449,7 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
}; };
let mut fully_expanded: SmallVector<ast::Stmt> = let mut fully_expanded: SmallVector<ast::Stmt> =
expand_mac_invoc(mac.unwrap(), None, attrs.into_attr_vec(), stmt.span, fld); expand_mac_invoc(mac.unwrap(), None, attrs.into(), stmt.span, fld);
// If this is a macro invocation with a semicolon, then apply that // If this is a macro invocation with a semicolon, then apply that
// semicolon to the final statement produced by expansion. // semicolon to the final statement produced by expansion.
@ -1054,7 +1054,7 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> { fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
expr.and_then(|expr| match expr.node { expr.and_then(|expr| match expr.node {
ast::ExprKind::Mac(mac) => ast::ExprKind::Mac(mac) =>
expand_mac_invoc(mac, None, expr.attrs.into_attr_vec(), expr.span, self), expand_mac_invoc(mac, None, expr.attrs.into(), expr.span, self),
_ => Some(expand_expr(expr, self)), _ => Some(expand_expr(expr, self)),
}) })
} }

View file

@ -250,7 +250,7 @@ pub mod rt {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Lit(P(self.clone())), node: ast::ExprKind::Lit(P(self.clone())),
span: DUMMY_SP, span: DUMMY_SP,
attrs: None, attrs: ast::ThinVec::new(),
}).to_tokens(cx) }).to_tokens(cx)
} }
} }
@ -281,7 +281,7 @@ pub mod rt {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Lit(P(dummy_spanned(lit))), node: ast::ExprKind::Lit(P(dummy_spanned(lit))),
span: DUMMY_SP, span: DUMMY_SP,
attrs: None, attrs: ast::ThinVec::new(),
}); });
if *self >= 0 { if *self >= 0 {
return lit.to_tokens(cx); return lit.to_tokens(cx);
@ -290,7 +290,7 @@ pub mod rt {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Unary(ast::UnOp::Neg, lit), node: ast::ExprKind::Unary(ast::UnOp::Neg, lit),
span: DUMMY_SP, span: DUMMY_SP,
attrs: None, attrs: ast::ThinVec::new(),
}).to_tokens(cx) }).to_tokens(cx)
} }
} }

View file

@ -20,7 +20,6 @@
use ast::*; use ast::*;
use ast; use ast;
use attr::{ThinAttributes, ThinAttributesExt};
use codemap::{respan, Span, Spanned}; use codemap::{respan, Span, Spanned};
use parse::token::{self, keywords}; use parse::token::{self, keywords};
use ptr::P; use ptr::P;
@ -336,8 +335,8 @@ pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribut
attrs.move_flat_map(|x| fld.fold_attribute(x)) attrs.move_flat_map(|x| fld.fold_attribute(x))
} }
pub fn fold_thin_attrs<T: Folder>(attrs: ThinAttributes, fld: &mut T) -> ThinAttributes { pub fn fold_thin_attrs<T: Folder>(attrs: ThinVec<Attribute>, fld: &mut T) -> ThinVec<Attribute> {
attrs.map_thin_attrs(|v| fold_attrs(v, fld)) fold_attrs(attrs.into(), fld).into()
} }
pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm { pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
@ -498,7 +497,7 @@ pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
pat: fld.fold_pat(pat), pat: fld.fold_pat(pat),
init: init.map(|e| fld.fold_expr(e)), init: init.map(|e| fld.fold_expr(e)),
span: fld.new_span(span), span: fld.new_span(span),
attrs: attrs.map_thin_attrs(|v| fold_attrs(v, fld)), attrs: fold_attrs(attrs.into(), fld).into(),
}) })
} }
@ -1300,7 +1299,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)), ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)),
}, },
span: folder.new_span(span), span: folder.new_span(span),
attrs: attrs.map_thin_attrs(|v| fold_attrs(v, folder)), attrs: fold_attrs(attrs.into(), folder).into(),
} }
} }
@ -1348,7 +1347,7 @@ pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
StmtKind::Mac(mac, semi, attrs) => SmallVector::one(Spanned { StmtKind::Mac(mac, semi, attrs) => SmallVector::one(Spanned {
node: StmtKind::Mac(mac.map(|m| folder.fold_mac(m)), node: StmtKind::Mac(mac.map(|m| folder.fold_mac(m)),
semi, semi,
attrs.map_thin_attrs(|v| fold_attrs(v, folder))), fold_attrs(attrs.into(), folder).into()),
span: span span: span
}) })
} }

View file

@ -73,6 +73,9 @@ pub mod util {
pub mod parser_testing; pub mod parser_testing;
pub mod small_vector; pub mod small_vector;
pub mod move_map; pub mod move_map;
mod thin_vec;
pub use self::thin_vec::ThinVec;
} }
pub mod diagnostics { pub mod diagnostics {

View file

@ -672,6 +672,7 @@ mod tests {
use ptr::P; use ptr::P;
use util::parser_testing::{string_to_tts, string_to_parser}; use util::parser_testing::{string_to_tts, string_to_parser};
use util::parser_testing::{string_to_expr, string_to_item, string_to_stmt}; use util::parser_testing::{string_to_expr, string_to_item, string_to_stmt};
use util::ThinVec;
// produce a codemap::span // produce a codemap::span
fn sp(a: u32, b: u32) -> Span { fn sp(a: u32, b: u32) -> Span {
@ -693,7 +694,7 @@ mod tests {
), ),
}), }),
span: sp(0, 1), span: sp(0, 1),
attrs: None, attrs: ThinVec::new(),
})) }))
} }
@ -716,7 +717,7 @@ mod tests {
) )
}), }),
span: sp(0, 6), span: sp(0, 6),
attrs: None, attrs: ThinVec::new(),
})) }))
} }
@ -832,10 +833,10 @@ mod tests {
), ),
}), }),
span:sp(7,8), span:sp(7,8),
attrs: None, attrs: ThinVec::new(),
}))), }))),
span:sp(0,8), span:sp(0,8),
attrs: None, attrs: ThinVec::new(),
})) }))
} }
@ -855,7 +856,7 @@ mod tests {
), ),
}), }),
span: sp(0,1), span: sp(0,1),
attrs: None}), attrs: ThinVec::new()}),
ast::DUMMY_NODE_ID), ast::DUMMY_NODE_ID),
span: sp(0,1)})) span: sp(0,1)}))
@ -950,7 +951,7 @@ mod tests {
), ),
}), }),
span: sp(17,18), span: sp(17,18),
attrs: None,}), attrs: ThinVec::new(),}),
ast::DUMMY_NODE_ID), ast::DUMMY_NODE_ID),
span: sp(17,19)}), span: sp(17,19)}),
expr: None, expr: None,

View file

@ -37,7 +37,6 @@ use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::{Visibility, WhereClause}; use ast::{Visibility, WhereClause};
use attr::{ThinAttributes, ThinAttributesExt, AttributesExt};
use ast::{BinOpKind, UnOp}; use ast::{BinOpKind, UnOp};
use ast; use ast;
use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap}; use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap};
@ -55,6 +54,7 @@ use util::parser::{AssocOp, Fixity};
use print::pprust; use print::pprust;
use ptr::P; use ptr::P;
use parse::PResult; use parse::PResult;
use util::ThinVec;
use std::collections::HashSet; use std::collections::HashSet;
use std::mem; use std::mem;
@ -120,7 +120,7 @@ macro_rules! maybe_whole_expr {
_ => unreachable!() _ => unreachable!()
}; };
let span = $p.span; let span = $p.span;
Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), None)) Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), ThinVec::new()))
} }
token::Interpolated(token::NtBlock(_)) => { token::Interpolated(token::NtBlock(_)) => {
// FIXME: The following avoids an issue with lexical borrowck scopes, // FIXME: The following avoids an issue with lexical borrowck scopes,
@ -130,7 +130,7 @@ macro_rules! maybe_whole_expr {
_ => unreachable!() _ => unreachable!()
}; };
let span = $p.span; let span = $p.span;
Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), None)) Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), ThinVec::new()))
} }
_ => None _ => None
}; };
@ -316,12 +316,12 @@ pub struct ModulePathError {
pub enum LhsExpr { pub enum LhsExpr {
NotYetParsed, NotYetParsed,
AttributesParsed(ThinAttributes), AttributesParsed(ThinVec<Attribute>),
AlreadyParsed(P<Expr>), AlreadyParsed(P<Expr>),
} }
impl From<Option<ThinAttributes>> for LhsExpr { impl From<Option<ThinVec<Attribute>>> for LhsExpr {
fn from(o: Option<ThinAttributes>) -> Self { fn from(o: Option<ThinVec<Attribute>>) -> Self {
if let Some(attrs) = o { if let Some(attrs) = o {
LhsExpr::AttributesParsed(attrs) LhsExpr::AttributesParsed(attrs)
} else { } else {
@ -1676,12 +1676,12 @@ impl<'a> Parser<'a> {
let lo = self.span.lo; let lo = self.span.lo;
let literal = P(self.parse_lit()?); let literal = P(self.parse_lit()?);
let hi = self.last_span.hi; let hi = self.last_span.hi;
let expr = self.mk_expr(lo, hi, ExprKind::Lit(literal), None); let expr = self.mk_expr(lo, hi, ExprKind::Lit(literal), ThinVec::new());
if minus_present { if minus_present {
let minus_hi = self.last_span.hi; let minus_hi = self.last_span.hi;
let unary = self.mk_unary(UnOp::Neg, expr); let unary = self.mk_unary(UnOp::Neg, expr);
Ok(self.mk_expr(minus_lo, minus_hi, unary, None)) Ok(self.mk_expr(minus_lo, minus_hi, unary, ThinVec::new()))
} else { } else {
Ok(expr) Ok(expr)
} }
@ -2039,13 +2039,13 @@ impl<'a> Parser<'a> {
}) })
} }
pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, node: ExprKind, attrs: ThinVec<Attribute>)
node: ExprKind, attrs: ThinAttributes) -> P<Expr> { -> P<Expr> {
P(Expr { P(Expr {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: node, node: node,
span: mk_sp(lo, hi), span: mk_sp(lo, hi),
attrs: attrs, attrs: attrs.into(),
}) })
} }
@ -2102,7 +2102,7 @@ impl<'a> Parser<'a> {
} }
pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos, pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos,
m: Mac_, attrs: ThinAttributes) -> P<Expr> { m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> {
P(Expr { P(Expr {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ExprKind::Mac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}), node: ExprKind::Mac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}),
@ -2111,7 +2111,7 @@ impl<'a> Parser<'a> {
}) })
} }
pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinAttributes) -> P<Expr> { pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinVec<Attribute>) -> P<Expr> {
let span = &self.span; let span = &self.span;
let lv_lit = P(codemap::Spanned { let lv_lit = P(codemap::Spanned {
node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)), node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)),
@ -2152,7 +2152,7 @@ impl<'a> Parser<'a> {
// //
// Therefore, prevent sub-parser from parsing // Therefore, prevent sub-parser from parsing
// attributes by giving them a empty "already parsed" list. // attributes by giving them a empty "already parsed" list.
let mut attrs = None; let mut attrs = ThinVec::new();
let lo = self.span.lo; let lo = self.span.lo;
let mut hi = self.span.hi; let mut hi = self.span.hi;
@ -2164,9 +2164,7 @@ impl<'a> Parser<'a> {
token::OpenDelim(token::Paren) => { token::OpenDelim(token::Paren) => {
self.bump(); self.bump();
let attrs = self.parse_inner_attributes()? attrs.extend(self.parse_inner_attributes()?);
.into_thin_attrs()
.prepend(attrs);
// (e) is parenthesized e // (e) is parenthesized e
// (e,) is a tuple with only one field, e // (e,) is a tuple with only one field, e
@ -2204,9 +2202,7 @@ impl<'a> Parser<'a> {
token::OpenDelim(token::Bracket) => { token::OpenDelim(token::Bracket) => {
self.bump(); self.bump();
let inner_attrs = self.parse_inner_attributes()? attrs.extend(self.parse_inner_attributes()?);
.into_thin_attrs();
attrs.update(|attrs| attrs.append(inner_attrs));
if self.check(&token::CloseDelim(token::Bracket)) { if self.check(&token::CloseDelim(token::Bracket)) {
// Empty vector. // Empty vector.
@ -2363,9 +2359,7 @@ impl<'a> Parser<'a> {
let mut fields = Vec::new(); let mut fields = Vec::new();
let mut base = None; let mut base = None;
let attrs = attrs.append( attrs.extend(self.parse_inner_attributes()?);
self.parse_inner_attributes()?
.into_thin_attrs());
while self.token != token::CloseDelim(token::Brace) { while self.token != token::CloseDelim(token::Brace) {
if self.eat(&token::DotDot) { if self.eat(&token::DotDot) {
@ -2432,25 +2426,24 @@ impl<'a> Parser<'a> {
} }
fn parse_or_use_outer_attributes(&mut self, fn parse_or_use_outer_attributes(&mut self,
already_parsed_attrs: Option<ThinAttributes>) already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, ThinAttributes> { -> PResult<'a, ThinVec<Attribute>> {
if let Some(attrs) = already_parsed_attrs { if let Some(attrs) = already_parsed_attrs {
Ok(attrs) Ok(attrs)
} else { } else {
self.parse_outer_attributes().map(|a| a.into_thin_attrs()) self.parse_outer_attributes().map(|a| a.into())
} }
} }
/// Parse a block or unsafe block /// Parse a block or unsafe block
pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode, pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode,
attrs: ThinAttributes) outer_attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
let outer_attrs = attrs;
self.expect(&token::OpenDelim(token::Brace))?; self.expect(&token::OpenDelim(token::Brace))?;
let inner_attrs = self.parse_inner_attributes()?.into_thin_attrs(); let mut attrs = outer_attrs;
let attrs = outer_attrs.append(inner_attrs); attrs.extend(self.parse_inner_attributes()?);
let blk = self.parse_block_tail(lo, blk_mode)?; let blk = self.parse_block_tail(lo, blk_mode)?;
return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), attrs)); return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), attrs));
@ -2458,7 +2451,7 @@ impl<'a> Parser<'a> {
/// parse a.b or a(13) or a[4] or just a /// parse a.b or a(13) or a[4] or just a
pub fn parse_dot_or_call_expr(&mut self, pub fn parse_dot_or_call_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>) already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
@ -2470,7 +2463,7 @@ impl<'a> Parser<'a> {
pub fn parse_dot_or_call_expr_with(&mut self, pub fn parse_dot_or_call_expr_with(&mut self,
e0: P<Expr>, e0: P<Expr>,
lo: BytePos, lo: BytePos,
attrs: ThinAttributes) mut attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
// Stitch the list of outer attributes onto the return value. // Stitch the list of outer attributes onto the return value.
// A little bit ugly, but the best way given the current code // A little bit ugly, but the best way given the current code
@ -2478,12 +2471,13 @@ impl<'a> Parser<'a> {
self.parse_dot_or_call_expr_with_(e0, lo) self.parse_dot_or_call_expr_with_(e0, lo)
.map(|expr| .map(|expr|
expr.map(|mut expr| { expr.map(|mut expr| {
expr.attrs.update(|a| a.prepend(attrs)); attrs.extend::<Vec<_>>(expr.attrs.into());
expr.attrs = attrs;
match expr.node { match expr.node {
ExprKind::If(..) | ExprKind::IfLet(..) => { ExprKind::If(..) | ExprKind::IfLet(..) => {
if !expr.attrs.as_attr_slice().is_empty() { if !expr.attrs.is_empty() {
// Just point to the first attribute in there... // Just point to the first attribute in there...
let span = expr.attrs.as_attr_slice()[0].span; let span = expr.attrs[0].span;
self.span_err(span, self.span_err(span,
"attributes are not yet allowed on `if` \ "attributes are not yet allowed on `if` \
@ -2531,7 +2525,7 @@ impl<'a> Parser<'a> {
es.insert(0, self_value); es.insert(0, self_value);
let id = spanned(ident_span.lo, ident_span.hi, ident); let id = spanned(ident_span.lo, ident_span.hi, ident);
let nd = self.mk_method_call(id, tys, es); let nd = self.mk_method_call(id, tys, es);
self.mk_expr(lo, hi, nd, None) self.mk_expr(lo, hi, nd, ThinVec::new())
} }
// Field access. // Field access.
_ => { _ => {
@ -2544,7 +2538,7 @@ impl<'a> Parser<'a> {
let id = spanned(ident_span.lo, ident_span.hi, ident); let id = spanned(ident_span.lo, ident_span.hi, ident);
let field = self.mk_field(self_value, id); let field = self.mk_field(self_value, id);
self.mk_expr(lo, ident_span.hi, field, None) self.mk_expr(lo, ident_span.hi, field, ThinVec::new())
} }
}) })
} }
@ -2556,7 +2550,7 @@ impl<'a> Parser<'a> {
// expr? // expr?
while self.eat(&token::Question) { while self.eat(&token::Question) {
let hi = self.last_span.hi; let hi = self.last_span.hi;
e = self.mk_expr(lo, hi, ExprKind::Try(e), None); e = self.mk_expr(lo, hi, ExprKind::Try(e), ThinVec::new());
} }
// expr.f // expr.f
@ -2584,7 +2578,7 @@ impl<'a> Parser<'a> {
Some(n) => { Some(n) => {
let id = spanned(dot, hi, n); let id = spanned(dot, hi, n);
let field = self.mk_tup_field(e, id); let field = self.mk_tup_field(e, id);
e = self.mk_expr(lo, hi, field, None); e = self.mk_expr(lo, hi, field, ThinVec::new());
} }
None => { None => {
let last_span = self.last_span; let last_span = self.last_span;
@ -2636,7 +2630,7 @@ impl<'a> Parser<'a> {
hi = self.last_span.hi; hi = self.last_span.hi;
let nd = self.mk_call(e, es); let nd = self.mk_call(e, es);
e = self.mk_expr(lo, hi, nd, None); e = self.mk_expr(lo, hi, nd, ThinVec::new());
} }
// expr[...] // expr[...]
@ -2647,7 +2641,7 @@ impl<'a> Parser<'a> {
hi = self.span.hi; hi = self.span.hi;
self.commit_expr_expecting(&ix, token::CloseDelim(token::Bracket))?; self.commit_expr_expecting(&ix, token::CloseDelim(token::Bracket))?;
let index = self.mk_index(e, ix); let index = self.mk_index(e, ix);
e = self.mk_expr(lo, hi, index, None) e = self.mk_expr(lo, hi, index, ThinVec::new())
} }
_ => return Ok(e) _ => return Ok(e)
} }
@ -2878,7 +2872,7 @@ impl<'a> Parser<'a> {
/// Parse a prefix-unary-operator expr /// Parse a prefix-unary-operator expr
pub fn parse_prefix_expr(&mut self, pub fn parse_prefix_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>) already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
let lo = self.span.lo; let lo = self.span.lo;
@ -2923,8 +2917,7 @@ impl<'a> Parser<'a> {
let blk = self.parse_block()?; let blk = self.parse_block()?;
let span = blk.span; let span = blk.span;
hi = span.hi; hi = span.hi;
let blk_expr = self.mk_expr(span.lo, span.hi, ExprKind::Block(blk), let blk_expr = self.mk_expr(span.lo, hi, ExprKind::Block(blk), ThinVec::new());
None);
ExprKind::InPlace(place, blk_expr) ExprKind::InPlace(place, blk_expr)
} }
token::Ident(..) if self.token.is_keyword(keywords::Box) => { token::Ident(..) if self.token.is_keyword(keywords::Box) => {
@ -2944,7 +2937,7 @@ impl<'a> Parser<'a> {
/// This parses an expression accounting for associativity and precedence of the operators in /// This parses an expression accounting for associativity and precedence of the operators in
/// the expression. /// the expression.
pub fn parse_assoc_expr(&mut self, pub fn parse_assoc_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>) already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
self.parse_assoc_expr_with(0, already_parsed_attrs.into()) self.parse_assoc_expr_with(0, already_parsed_attrs.into())
} }
@ -2997,13 +2990,13 @@ impl<'a> Parser<'a> {
// Special cases: // Special cases:
if op == AssocOp::As { if op == AssocOp::As {
let rhs = self.parse_ty()?; let rhs = self.parse_ty()?;
lhs = self.mk_expr(lhs_span.lo, rhs.span.hi, let (lo, hi) = (lhs_span.lo, rhs.span.hi);
ExprKind::Cast(lhs, rhs), None); lhs = self.mk_expr(lo, hi, ExprKind::Cast(lhs, rhs), ThinVec::new());
continue continue
} else if op == AssocOp::Colon { } else if op == AssocOp::Colon {
let rhs = self.parse_ty()?; let rhs = self.parse_ty()?;
lhs = self.mk_expr(lhs_span.lo, rhs.span.hi, let (lo, hi) = (lhs_span.lo, rhs.span.hi);
ExprKind::Type(lhs, rhs), None); lhs = self.mk_expr(lo, hi, ExprKind::Type(lhs, rhs), ThinVec::new());
continue continue
} else if op == AssocOp::DotDot || op == AssocOp::DotDotDot { } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot {
// If we didnt have to handle `x..`/`x...`, it would be pretty easy to // If we didnt have to handle `x..`/`x...`, it would be pretty easy to
@ -3029,7 +3022,7 @@ impl<'a> Parser<'a> {
}; };
let r = try!(self.mk_range(Some(lhs), rhs, limits)); let r = try!(self.mk_range(Some(lhs), rhs, limits));
lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, None); lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, ThinVec::new());
break break
} }
@ -3056,6 +3049,7 @@ impl<'a> Parser<'a> {
}), }),
}?; }?;
let (lo, hi) = (lhs_span.lo, rhs.span.hi);
lhs = match op { lhs = match op {
AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide |
AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor | AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor |
@ -3063,14 +3057,13 @@ impl<'a> Parser<'a> {
AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual | AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
AssocOp::Greater | AssocOp::GreaterEqual => { AssocOp::Greater | AssocOp::GreaterEqual => {
let ast_op = op.to_ast_binop().unwrap(); let ast_op = op.to_ast_binop().unwrap();
let (lhs_span, rhs_span) = (lhs_span, rhs.span);
let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs); let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None) self.mk_expr(lo, hi, binary, ThinVec::new())
} }
AssocOp::Assign => AssocOp::Assign =>
self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::Assign(lhs, rhs), None), self.mk_expr(lo, hi, ExprKind::Assign(lhs, rhs), ThinVec::new()),
AssocOp::Inplace => AssocOp::Inplace =>
self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::InPlace(lhs, rhs), None), self.mk_expr(lo, hi, ExprKind::InPlace(lhs, rhs), ThinVec::new()),
AssocOp::AssignOp(k) => { AssocOp::AssignOp(k) => {
let aop = match k { let aop = match k {
token::Plus => BinOpKind::Add, token::Plus => BinOpKind::Add,
@ -3084,9 +3077,8 @@ impl<'a> Parser<'a> {
token::Shl => BinOpKind::Shl, token::Shl => BinOpKind::Shl,
token::Shr => BinOpKind::Shr, token::Shr => BinOpKind::Shr,
}; };
let (lhs_span, rhs_span) = (lhs_span, rhs.span);
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs); let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None) self.mk_expr(lo, hi, aopexpr, ThinVec::new())
} }
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => { AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => {
self.bug("As, Colon, DotDot or DotDotDot branch reached") self.bug("As, Colon, DotDot or DotDotDot branch reached")
@ -3121,7 +3113,7 @@ impl<'a> Parser<'a> {
/// Parse prefix-forms of range notation: `..expr`, `..`, `...expr` /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr`
fn parse_prefix_range_expr(&mut self, fn parse_prefix_range_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>) already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot); debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot);
let tok = self.token.clone(); let tok = self.token.clone();
@ -3166,7 +3158,7 @@ impl<'a> Parser<'a> {
} }
/// Parse an 'if' or 'if let' expression ('if' token already eaten) /// Parse an 'if' or 'if let' expression ('if' token already eaten)
pub fn parse_if_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> { pub fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
if self.check_keyword(keywords::Let) { if self.check_keyword(keywords::Let) {
return self.parse_if_let_expr(attrs); return self.parse_if_let_expr(attrs);
} }
@ -3184,7 +3176,7 @@ impl<'a> Parser<'a> {
} }
/// Parse an 'if let' expression ('if' token already eaten) /// Parse an 'if let' expression ('if' token already eaten)
pub fn parse_if_let_expr(&mut self, attrs: ThinAttributes) pub fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
let lo = self.last_span.lo; let lo = self.last_span.lo;
self.expect_keyword(keywords::Let)?; self.expect_keyword(keywords::Let)?;
@ -3205,7 +3197,7 @@ impl<'a> Parser<'a> {
pub fn parse_lambda_expr(&mut self, pub fn parse_lambda_expr(&mut self,
lo: BytePos, lo: BytePos,
capture_clause: CaptureBy, capture_clause: CaptureBy,
attrs: ThinAttributes) attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>> -> PResult<'a, P<Expr>>
{ {
let decl = self.parse_fn_block_decl()?; let decl = self.parse_fn_block_decl()?;
@ -3240,24 +3232,24 @@ impl<'a> Parser<'a> {
// `else` token already eaten // `else` token already eaten
pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
if self.eat_keyword(keywords::If) { if self.eat_keyword(keywords::If) {
return self.parse_if_expr(None); return self.parse_if_expr(ThinVec::new());
} else { } else {
let blk = self.parse_block()?; let blk = self.parse_block()?;
return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), None)); return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), ThinVec::new()));
} }
} }
/// Parse a 'for' .. 'in' expression ('for' token already eaten) /// Parse a 'for' .. 'in' expression ('for' token already eaten)
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
span_lo: BytePos, span_lo: BytePos,
attrs: ThinAttributes) -> PResult<'a, P<Expr>> { mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
// Parse: `for <src_pat> in <src_expr> <src_loop_block>` // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
let pat = self.parse_pat()?; let pat = self.parse_pat()?;
self.expect_keyword(keywords::In)?; self.expect_keyword(keywords::In)?;
let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?;
let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
let attrs = attrs.append(iattrs.into_thin_attrs()); attrs.extend(iattrs);
let hi = self.last_span.hi; let hi = self.last_span.hi;
@ -3269,13 +3261,13 @@ impl<'a> Parser<'a> {
/// Parse a 'while' or 'while let' expression ('while' token already eaten) /// Parse a 'while' or 'while let' expression ('while' token already eaten)
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
span_lo: BytePos, span_lo: BytePos,
attrs: ThinAttributes) -> PResult<'a, P<Expr>> { mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
if self.token.is_keyword(keywords::Let) { if self.token.is_keyword(keywords::Let) {
return self.parse_while_let_expr(opt_ident, span_lo, attrs); return self.parse_while_let_expr(opt_ident, span_lo, attrs);
} }
let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?;
let (iattrs, body) = self.parse_inner_attrs_and_block()?; let (iattrs, body) = self.parse_inner_attrs_and_block()?;
let attrs = attrs.append(iattrs.into_thin_attrs()); attrs.extend(iattrs);
let hi = body.span.hi; let hi = body.span.hi;
return Ok(self.mk_expr(span_lo, hi, ExprKind::While(cond, body, opt_ident), return Ok(self.mk_expr(span_lo, hi, ExprKind::While(cond, body, opt_ident),
attrs)); attrs));
@ -3284,13 +3276,13 @@ impl<'a> Parser<'a> {
/// Parse a 'while let' expression ('while' token already eaten) /// Parse a 'while let' expression ('while' token already eaten)
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
span_lo: BytePos, span_lo: BytePos,
attrs: ThinAttributes) -> PResult<'a, P<Expr>> { mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
self.expect_keyword(keywords::Let)?; self.expect_keyword(keywords::Let)?;
let pat = self.parse_pat()?; let pat = self.parse_pat()?;
self.expect(&token::Eq)?; self.expect(&token::Eq)?;
let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?;
let (iattrs, body) = self.parse_inner_attrs_and_block()?; let (iattrs, body) = self.parse_inner_attrs_and_block()?;
let attrs = attrs.append(iattrs.into_thin_attrs()); attrs.extend(iattrs);
let hi = body.span.hi; let hi = body.span.hi;
return Ok(self.mk_expr(span_lo, hi, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs)); return Ok(self.mk_expr(span_lo, hi, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs));
} }
@ -3298,15 +3290,15 @@ impl<'a> Parser<'a> {
// parse `loop {...}`, `loop` token already eaten // parse `loop {...}`, `loop` token already eaten
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
span_lo: BytePos, span_lo: BytePos,
attrs: ThinAttributes) -> PResult<'a, P<Expr>> { mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
let (iattrs, body) = self.parse_inner_attrs_and_block()?; let (iattrs, body) = self.parse_inner_attrs_and_block()?;
let attrs = attrs.append(iattrs.into_thin_attrs()); attrs.extend(iattrs);
let hi = body.span.hi; let hi = body.span.hi;
Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs)) Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs))
} }
// `match` token already eaten // `match` token already eaten
fn parse_match_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> { fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
let match_span = self.last_span; let match_span = self.last_span;
let lo = self.last_span.lo; let lo = self.last_span.lo;
let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL,
@ -3318,8 +3310,8 @@ impl<'a> Parser<'a> {
} }
return Err(e) return Err(e)
} }
let attrs = attrs.append( attrs.extend(self.parse_inner_attributes()?);
self.parse_inner_attributes()?.into_thin_attrs());
let mut arms: Vec<Arm> = Vec::new(); let mut arms: Vec<Arm> = Vec::new();
while self.token != token::CloseDelim(token::Brace) { while self.token != token::CloseDelim(token::Brace) {
match self.parse_arm() { match self.parse_arm() {
@ -3392,7 +3384,7 @@ impl<'a> Parser<'a> {
/// Parse an expression, subject to the given restrictions /// Parse an expression, subject to the given restrictions
pub fn parse_expr_res(&mut self, r: Restrictions, pub fn parse_expr_res(&mut self, r: Restrictions,
already_parsed_attrs: Option<ThinAttributes>) already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, P<Expr>> { -> PResult<'a, P<Expr>> {
self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs)) self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
} }
@ -3590,7 +3582,7 @@ impl<'a> Parser<'a> {
(None, self.parse_path(PathStyle::Expr)?) (None, self.parse_path(PathStyle::Expr)?)
}; };
let hi = self.last_span.hi; let hi = self.last_span.hi;
Ok(self.mk_expr(lo, hi, ExprKind::Path(qself, path), None)) Ok(self.mk_expr(lo, hi, ExprKind::Path(qself, path), ThinVec::new()))
} else { } else {
self.parse_pat_literal_maybe_minus() self.parse_pat_literal_maybe_minus()
} }
@ -3685,7 +3677,8 @@ impl<'a> Parser<'a> {
token::DotDotDot => { token::DotDotDot => {
// Parse range // Parse range
let hi = self.last_span.hi; let hi = self.last_span.hi;
let begin = self.mk_expr(lo, hi, ExprKind::Path(qself, path), None); let begin =
self.mk_expr(lo, hi, ExprKind::Path(qself, path), ThinVec::new());
self.bump(); self.bump();
let end = self.parse_pat_range_end()?; let end = self.parse_pat_range_end()?;
pat = PatKind::Range(begin, end); pat = PatKind::Range(begin, end);
@ -3785,7 +3778,7 @@ impl<'a> Parser<'a> {
} }
/// Parse a local variable declaration /// Parse a local variable declaration
fn parse_local(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Local>> { fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
let lo = self.span.lo; let lo = self.span.lo;
let pat = self.parse_pat()?; let pat = self.parse_pat()?;
@ -3805,7 +3798,7 @@ impl<'a> Parser<'a> {
} }
/// Parse a "let" stmt /// Parse a "let" stmt
fn parse_let(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Decl>> { fn parse_let(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Decl>> {
let lo = self.span.lo; let lo = self.span.lo;
let local = self.parse_local(attrs)?; let local = self.parse_local(attrs)?;
Ok(P(spanned(lo, self.last_span.hi, DeclKind::Local(local)))) Ok(P(spanned(lo, self.last_span.hi, DeclKind::Local(local))))
@ -3925,7 +3918,7 @@ impl<'a> Parser<'a> {
Ok(Some(if self.check_keyword(keywords::Let) { Ok(Some(if self.check_keyword(keywords::Let) {
self.expect_keyword(keywords::Let)?; self.expect_keyword(keywords::Let)?;
let decl = self.parse_let(attrs.into_thin_attrs())?; let decl = self.parse_let(attrs.into())?;
let hi = decl.span.hi; let hi = decl.span.hi;
let stmt = StmtKind::Decl(decl, ast::DUMMY_NODE_ID); let stmt = StmtKind::Decl(decl, ast::DUMMY_NODE_ID);
spanned(lo, hi, stmt) spanned(lo, hi, stmt)
@ -3980,7 +3973,7 @@ impl<'a> Parser<'a> {
if id.name == keywords::Invalid.name() { if id.name == keywords::Invalid.name() {
let mac = P(spanned(lo, hi, Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })); let mac = P(spanned(lo, hi, Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }));
let stmt = StmtKind::Mac(mac, style, attrs.into_thin_attrs()); let stmt = StmtKind::Mac(mac, style, attrs.into());
spanned(lo, hi, stmt) spanned(lo, hi, stmt)
} else { } else {
// if it has a special ident, it's definitely an item // if it has a special ident, it's definitely an item
@ -4036,7 +4029,7 @@ impl<'a> Parser<'a> {
// Remainder are line-expr stmts. // Remainder are line-expr stmts.
let e = self.parse_expr_res( let e = self.parse_expr_res(
Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into_thin_attrs()))?; Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into()))?;
let hi = e.span.hi; let hi = e.span.hi;
let stmt = StmtKind::Expr(e, ast::DUMMY_NODE_ID); let stmt = StmtKind::Expr(e, ast::DUMMY_NODE_ID);
spanned(lo, hi, stmt) spanned(lo, hi, stmt)
@ -4111,7 +4104,7 @@ impl<'a> Parser<'a> {
_ => { _ => {
let e = self.mk_mac_expr(span.lo, span.hi, let e = self.mk_mac_expr(span.lo, span.hi,
mac.and_then(|m| m.node), mac.and_then(|m| m.node),
None); ThinVec::new());
let lo = e.span.lo; let lo = e.span.lo;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;

View file

@ -14,7 +14,6 @@ use abi::{self, Abi};
use ast::{self, TokenTree, BlockCheckMode, PatKind}; use ast::{self, TokenTree, BlockCheckMode, PatKind};
use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
use ast::Attribute; use ast::Attribute;
use attr::ThinAttributesExt;
use util::parser::AssocOp; use util::parser::AssocOp;
use attr; use attr;
use attr::{AttrMetaMethods, AttributeMethods}; use attr::{AttrMetaMethods, AttributeMethods};
@ -1606,7 +1605,7 @@ impl<'a> State<'a> {
} }
ast::StmtKind::Mac(ref mac, style, ref attrs) => { ast::StmtKind::Mac(ref mac, style, ref attrs) => {
try!(self.space_if_not_bol()); try!(self.space_if_not_bol());
try!(self.print_outer_attributes(attrs.as_attr_slice())); try!(self.print_outer_attributes(&attrs));
let delim = match style { let delim = match style {
ast::MacStmtStyle::Braces => token::Brace, ast::MacStmtStyle::Braces => token::Brace,
_ => token::Paren _ => token::Paren
@ -1946,7 +1945,7 @@ impl<'a> State<'a> {
is_inline: bool) -> io::Result<()> { is_inline: bool) -> io::Result<()> {
try!(self.maybe_print_comment(expr.span.lo)); try!(self.maybe_print_comment(expr.span.lo));
let attrs = expr.attrs.as_attr_slice(); let attrs = &expr.attrs;
if is_inline { if is_inline {
try!(self.print_outer_attributes_inline(attrs)); try!(self.print_outer_attributes_inline(attrs));
} else { } else {
@ -2090,9 +2089,7 @@ impl<'a> State<'a> {
let i_expr = body.expr.as_ref().unwrap(); let i_expr = body.expr.as_ref().unwrap();
match i_expr.node { match i_expr.node {
ast::ExprKind::Block(ref blk) => { ast::ExprKind::Block(ref blk) => {
try!(self.print_block_unclosed_with_attrs( try!(self.print_block_unclosed_with_attrs(&blk, &i_expr.attrs));
&blk,
i_expr.attrs.as_attr_slice()));
} }
_ => { _ => {
// this is a bare expression // this is a bare expression
@ -2281,7 +2278,7 @@ impl<'a> State<'a> {
try!(self.maybe_print_comment(decl.span.lo)); try!(self.maybe_print_comment(decl.span.lo));
match decl.node { match decl.node {
ast::DeclKind::Local(ref loc) => { ast::DeclKind::Local(ref loc) => {
try!(self.print_outer_attributes(loc.attrs.as_attr_slice())); try!(self.print_outer_attributes(&loc.attrs));
try!(self.space_if_not_bol()); try!(self.space_if_not_bol());
try!(self.ibox(INDENT_UNIT)); try!(self.ibox(INDENT_UNIT));
try!(self.word_nbsp("let")); try!(self.word_nbsp("let"));

View file

@ -604,10 +604,10 @@ fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> {
mk_test_desc_and_fn_rec(cx, test) mk_test_desc_and_fn_rec(cx, test)
}).collect()), }).collect()),
span: DUMMY_SP, span: DUMMY_SP,
attrs: None, attrs: ast::ThinVec::new(),
})), })),
span: DUMMY_SP, span: DUMMY_SP,
attrs: None, attrs: ast::ThinVec::new(),
}) })
} }

View file

@ -0,0 +1,59 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// A vector type optimized for cases where this size is usually 0 (c.f. `SmallVector`).
/// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
/// which uses only a single (null) pointer.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct ThinVec<T>(Option<Box<Vec<T>>>);
impl<T> ThinVec<T> {
pub fn new() -> Self {
ThinVec(None)
}
}
impl<T> From<Vec<T>> for ThinVec<T> {
fn from(vec: Vec<T>) -> Self {
if vec.is_empty() {
ThinVec(None)
} else {
ThinVec(Some(Box::new(vec)))
}
}
}
impl<T> Into<Vec<T>> for ThinVec<T> {
fn into(self) -> Vec<T> {
match self {
ThinVec(None) => Vec::new(),
ThinVec(Some(vec)) => *vec,
}
}
}
impl<T> ::std::ops::Deref for ThinVec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
match *self {
ThinVec(None) => &[],
ThinVec(Some(ref vec)) => vec,
}
}
}
impl<T> Extend<T> for ThinVec<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
match *self {
ThinVec(Some(ref mut vec)) => vec.extend(iter),
ThinVec(None) => *self = iter.into_iter().collect::<Vec<_>>().into(),
}
}
}

View file

@ -25,7 +25,6 @@
use abi::Abi; use abi::Abi;
use ast::*; use ast::*;
use attr::ThinAttributesExt;
use codemap::{Span, Spanned}; use codemap::{Span, Spanned};
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
@ -185,7 +184,7 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
} }
pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
for attr in local.attrs.as_attr_slice() { for attr in local.attrs.iter() {
visitor.visit_attribute(attr); visitor.visit_attribute(attr);
} }
visitor.visit_pat(&local.pat); visitor.visit_pat(&local.pat);
@ -619,7 +618,7 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
} }
StmtKind::Mac(ref mac, _, ref attrs) => { StmtKind::Mac(ref mac, _, ref attrs) => {
visitor.visit_mac(mac); visitor.visit_mac(mac);
for attr in attrs.as_attr_slice() { for attr in attrs.iter() {
visitor.visit_attribute(attr); visitor.visit_attribute(attr);
} }
} }
@ -638,7 +637,7 @@ pub fn walk_mac<'v, V: Visitor<'v>>(_: &mut V, _: &'v Mac) {
} }
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
for attr in expression.attrs.as_attr_slice() { for attr in expression.attrs.iter() {
visitor.visit_attribute(attr); visitor.visit_attribute(attr);
} }
match expression.node { match expression.node {

View file

@ -260,6 +260,6 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
expn_id: expn_id, expn_id: expn_id,
}), }),
span: sp, span: sp,
attrs: None, attrs: ast::ThinVec::new(),
})) }))
} }

View file

@ -70,7 +70,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, self.path()), node: ast::ExprKind::Path(None, self.path()),
span: self.span, span: self.span,
attrs: None, attrs: ast::ThinVec::new(),
})) }))
} }

View file

@ -149,7 +149,7 @@ fn stmt_let_undescore(cx: &mut ExtCtxt,
init: Some(expr), init: Some(expr),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: sp, span: sp,
attrs: None, attrs: ast::ThinVec::new(),
}); });
let decl = respan(sp, ast::DeclKind::Local(local)); let decl = respan(sp, ast::DeclKind::Local(local));
respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)) respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))

View file

@ -86,7 +86,7 @@ fn check_expr_attrs(es: &str, expected: &[&str]) {
let actual = &e.attrs; let actual = &e.attrs;
str_compare(es, str_compare(es,
&expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(), &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
actual.as_attr_slice(), &actual,
pprust::attribute_to_string); pprust::attribute_to_string);
} }