提交 f0beba02 编写于 作者: M Marvin Löbel

Moved and refactored ThinAttributes

上级 2a8f358d
......@@ -41,7 +41,8 @@
use syntax::attr::{self, AttrMetaMethods};
use syntax::codemap::Span;
use syntax::parse::token::InternedString;
use syntax::ast::{self, ThinAttributesExt};
use syntax::ast;
use syntax::attr::ThinAttributesExt;
use rustc_front::hir;
use rustc_front::util;
use rustc_front::intravisit as hir_visit;
......@@ -674,7 +675,7 @@ fn visit_pat(&mut self, p: &hir::Pat) {
}
fn visit_expr(&mut self, e: &hir::Expr) {
self.with_lint_attrs(e.attrs.as_attrs(), |cx| {
self.with_lint_attrs(e.attrs.as_attr_slice(), |cx| {
run_lints!(cx, check_expr, late_passes, e);
hir_visit::walk_expr(cx, e);
})
......@@ -737,7 +738,7 @@ fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) {
}
fn visit_local(&mut self, l: &hir::Local) {
self.with_lint_attrs(l.attrs.as_attrs(), |cx| {
self.with_lint_attrs(l.attrs.as_attr_slice(), |cx| {
run_lints!(cx, check_local, late_passes, l);
hir_visit::walk_local(cx, l);
})
......
......@@ -13,7 +13,8 @@
use hir::*;
use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem};
use syntax::ast::{MetaWord, MetaList, MetaNameValue, ThinAttributesExt};
use syntax::ast::{MetaWord, MetaList, MetaNameValue};
use syntax::attr::ThinAttributesExt;
use hir;
use syntax::codemap::{respan, Span, Spanned};
use syntax::owned_slice::OwnedSlice;
......@@ -508,7 +509,7 @@ pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
pat: fld.fold_pat(pat),
init: init.map(|e| fld.fold_expr(e)),
span: fld.new_span(span),
attrs: attrs.map_opt_attrs(|attrs| fold_attrs(attrs, fld)),
attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs, fld)),
}
})
}
......@@ -1172,7 +1173,7 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
}
},
span: folder.new_span(span),
attrs: attrs.map_opt_attrs(|attrs| fold_attrs(attrs, folder)),
attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs, folder)),
}
}
......
......@@ -41,7 +41,7 @@
use syntax::abi::Abi;
use syntax::ast::{Name, Ident, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, CrateConfig};
use syntax::ast::ThinAttributes;
use syntax::attr::ThinAttributes;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::InternedString;
use syntax::ptr::P;
......
......@@ -66,6 +66,7 @@
use std::collections::BTreeMap;
use std::collections::HashMap;
use syntax::ast::*;
use syntax::attr::{ThinAttributes, ThinAttributesExt};
use syntax::ptr::P;
use syntax::codemap::{respan, Spanned, Span};
use syntax::owned_slice::OwnedSlice;
......@@ -1219,8 +1220,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// merge attributes into the inner expression.
return lower_expr(lctx, ex).map(|mut ex| {
ex.attrs.update(|attrs| {
// FIXME: Badly named
attrs.prepend_outer(e.attrs.clone())
attrs.prepend(e.attrs.clone())
});
ex
});
......
......@@ -45,6 +45,7 @@
pub use self::Visibility::*;
pub use self::PathParameters::*;
use attr::ThinAttributes;
use codemap::{Span, Spanned, DUMMY_SP, ExpnId};
use abi::Abi;
use ast_util;
......@@ -1952,98 +1953,6 @@ pub struct MacroDef {
pub body: Vec<TokenTree>,
}
/// A list of attributes, behind a optional box as
/// a space optimization.
pub type ThinAttributes = Option<Box<Vec<Attribute>>>;
pub trait ThinAttributesExt {
fn map_opt_attrs<F>(self, f: F) -> Self
where F: FnOnce(Vec<Attribute>) -> Vec<Attribute>;
fn prepend_outer(mut self, attrs: Self) -> Self;
fn append_inner(mut self, attrs: Self) -> Self;
fn update<F>(&mut self, f: F)
where Self: Sized,
F: FnOnce(Self) -> Self;
fn as_attrs(&self) -> &[Attribute];
fn into_attrs(self) -> Vec<Attribute>;
}
// FIXME: Rename inner/outer
// FIXME: Rename opt_attrs
impl ThinAttributesExt for ThinAttributes {
fn map_opt_attrs<F>(self, f: F) -> Self
where F: FnOnce(Vec<Attribute>) -> Vec<Attribute> {
// This is kinda complicated... Ensure the function is
// always called, and that None inputs or results are
// correctly handled.
if let Some(mut b) = self {
use std::mem::replace;
let vec = replace(&mut *b, Vec::new());
let vec = f(vec);
if vec.len() == 0 {
None
} else {
replace(&mut*b, vec);
Some(b)
}
} else {
f(Vec::new()).into_opt_attrs()
}
}
fn prepend_outer(self, attrs: ThinAttributes) -> Self {
attrs.map_opt_attrs(|mut attrs| {
attrs.extend(self.into_attrs());
attrs
})
}
fn append_inner(self, attrs: ThinAttributes) -> Self {
self.map_opt_attrs(|mut self_| {
self_.extend(attrs.into_attrs());
self_
})
}
fn update<F>(&mut self, f: F)
where Self: Sized,
F: FnOnce(ThinAttributes) -> ThinAttributes
{
let self_ = f(self.take());
*self = self_;
}
fn as_attrs(&self) -> &[Attribute] {
match *self {
Some(ref b) => b,
None => &[],
}
}
fn into_attrs(self) -> Vec<Attribute> {
match self {
Some(b) => *b,
None => Vec::new(),
}
}
}
pub trait AttributesExt {
fn into_opt_attrs(self) -> ThinAttributes;
}
impl AttributesExt for Vec<Attribute> {
fn into_opt_attrs(self) -> ThinAttributes {
if self.len() == 0 {
None
} else {
Some(Box::new(self))
}
}
}
#[cfg(test)]
mod tests {
use serialize;
......
......@@ -16,8 +16,8 @@
use ast;
use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, MetaList};
use ast::{Stmt, StmtDecl, StmtExpr, StmtMac, StmtSemi, DeclItem, DeclLocal, ThinAttributes};
use ast::{Expr, ThinAttributesExt, Item, Local, Decl};
use ast::{Stmt, StmtDecl, StmtExpr, StmtMac, StmtSemi, DeclItem, DeclLocal};
use ast::{Expr, Item, Local, Decl};
use codemap::{Span, Spanned, spanned, dummy_spanned};
use codemap::BytePos;
use diagnostic::SpanHandler;
......@@ -723,6 +723,96 @@ fn is_ffi_safe(self) -> bool {
}
}
/// 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> {
// This is kinda complicated... Ensure the function is
// always called, and that None inputs or results are
// correctly handled.
if let Some(mut b) = self {
use std::mem::replace;
let vec = replace(&mut *b, Vec::new());
let vec = f(vec);
if vec.len() == 0 {
None
} else {
replace(&mut*b, vec);
Some(b)
}
} else {
f(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))
}
}
}
/// A cheap way to add Attributes to an AST node.
pub trait WithAttrs {
// FIXME: Could be extended to anything IntoIter<Item=Attribute>
......@@ -732,7 +822,7 @@ pub trait WithAttrs {
impl WithAttrs for P<Expr> {
fn with_attrs(self, attrs: ThinAttributes) -> Self {
self.map(|mut e| {
e.attrs.update(|a| a.append_inner(attrs));
e.attrs.update(|a| a.append(attrs));
e
})
}
......@@ -741,7 +831,7 @@ fn with_attrs(self, attrs: ThinAttributes) -> Self {
impl WithAttrs for P<Item> {
fn with_attrs(self, attrs: ThinAttributes) -> Self {
self.map(|Item { ident, attrs: mut ats, id, node, vis, span }| {
ats.extend(attrs.into_attrs());
ats.extend(attrs.into_attr_vec());
Item {
ident: ident,
attrs: ats,
......@@ -757,7 +847,7 @@ fn with_attrs(self, attrs: ThinAttributes) -> Self {
impl WithAttrs for P<Local> {
fn with_attrs(self, attrs: ThinAttributes) -> Self {
self.map(|Local { pat, ty, init, id, span, attrs: mut ats }| {
ats.update(|a| a.append_inner(attrs));
ats.update(|a| a.append(attrs));
Local {
pat: pat,
ty: ty,
......@@ -794,7 +884,7 @@ fn with_attrs(self, attrs: ThinAttributes) -> Self {
StmtExpr(expr, id) => StmtExpr(expr.with_attrs(attrs), id),
StmtSemi(expr, id) => StmtSemi(expr.with_attrs(attrs), id),
StmtMac(mac, style, mut ats) => {
ats.update(|a| a.append_inner(attrs));
ats.update(|a| a.append(attrs));
StmtMac(mac, style, ats)
}
},
......
......@@ -54,7 +54,7 @@ fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
// Anything else is always required, and thus has to error out
// in case of a cfg attr.
//
// NB: This intentionally not part of the fold_expr() function
// NB: This is intentionally not part of the fold_expr() function
// in order for fold_opt_expr() to be able to avoid this check
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
self.diagnostic.span_err(attr.span,
......
......@@ -20,6 +20,7 @@
use ast::*;
use ast;
use attr::ThinAttributesExt;
use ast_util;
use codemap::{respan, Span, Spanned};
use owned_slice::OwnedSlice;
......@@ -522,7 +523,7 @@ pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
pat: fld.fold_pat(pat),
init: init.map(|e| fld.fold_expr(e)),
span: fld.new_span(span),
attrs: attrs.map_opt_attrs(|v| fold_attrs(v, fld)),
attrs: attrs.map_thin_attrs(|v| fold_attrs(v, fld)),
})
}
......@@ -1339,7 +1340,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
ExprParen(ex) => ExprParen(folder.fold_expr(ex))
},
span: folder.new_span(span),
attrs: attrs.map_opt_attrs(|v| fold_attrs(v, folder)),
attrs: attrs.map_thin_attrs(|v| fold_attrs(v, folder)),
}
}
......@@ -1388,7 +1389,7 @@ pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
StmtMac(mac, semi, attrs) => SmallVector::one(P(Spanned {
node: StmtMac(mac.map(|m| folder.fold_mac(m)),
semi,
attrs.map_opt_attrs(|v| fold_attrs(v, folder))),
attrs.map_thin_attrs(|v| fold_attrs(v, folder))),
span: span
}))
}
......
......@@ -56,7 +56,7 @@
use ast::{UnnamedField, UnsafeBlock};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::{Visibility, WhereClause};
use ast::{ThinAttributes, ThinAttributesExt, AttributesExt};
use attr::{ThinAttributes, ThinAttributesExt, AttributesExt};
use ast;
use ast_util::{self, ident_to_path};
use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap};
......@@ -2053,8 +2053,8 @@ fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> {
try!(self.bump());
let attrs = try!(self.parse_inner_attributes())
.into_opt_attrs()
.prepend_outer(attrs);
.into_thin_attrs()
.prepend(attrs);
// (e) is parenthesized e
// (e,) is a tuple with only one field, e
......@@ -2102,8 +2102,8 @@ fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> {
try!(self.bump());
let inner_attrs = try!(self.parse_inner_attributes())
.into_opt_attrs();
attrs.update(|attrs| attrs.append_inner(inner_attrs));
.into_thin_attrs();
attrs.update(|attrs| attrs.append(inner_attrs));
if self.check(&token::CloseDelim(token::Bracket)) {
// Empty vector.
......@@ -2257,9 +2257,9 @@ fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> {
let mut fields = Vec::new();
let mut base = None;
let attrs = attrs.append_inner(
let attrs = attrs.append(
try!(self.parse_inner_attributes())
.into_opt_attrs());
.into_thin_attrs());
while self.token != token::CloseDelim(token::Brace) {
if try!(self.eat(&token::DotDot) ){
......@@ -2300,7 +2300,7 @@ fn parse_or_use_outer_attributes(&mut self,
if let Some(attrs) = already_parsed_attrs {
Ok(attrs)
} else {
self.parse_outer_attributes().map(|a| a.into_opt_attrs())
self.parse_outer_attributes().map(|a| a.into_thin_attrs())
}
}
......@@ -2312,8 +2312,8 @@ pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode,
let outer_attrs = attrs;
try!(self.expect(&token::OpenDelim(token::Brace)));
let inner_attrs = try!(self.parse_inner_attributes()).into_opt_attrs();
let attrs = outer_attrs.append_inner(inner_attrs);
let inner_attrs = try!(self.parse_inner_attributes()).into_thin_attrs();
let attrs = outer_attrs.append(inner_attrs);
let blk = try!(self.parse_block_tail(lo, blk_mode));
return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk), attrs));
......@@ -2339,12 +2339,12 @@ pub fn parse_dot_or_call_expr_with(&mut self,
self.parse_dot_or_call_expr_with_(e0)
.map(|expr|
expr.map(|mut expr| {
expr.attrs.update(|a| a.prepend_outer(attrs));
expr.attrs.update(|a| a.prepend(attrs));
match expr.node {
ExprIf(..) | ExprIfLet(..) => {
if !expr.attrs.as_attrs().is_empty() {
if !expr.attrs.as_attr_slice().is_empty() {
// Just point to the first attribute in there...
let span = expr.attrs.as_attrs()[0].span;
let span = expr.attrs.as_attr_slice()[0].span;
self.span_err(span,
"attributes are not yet allowed on `if` \
......@@ -3012,7 +3012,7 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>,
try!(self.expect_keyword(keywords::In));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None));
let (iattrs, loop_block) = try!(self.parse_inner_attrs_and_block());
let attrs = attrs.append_inner(iattrs.into_opt_attrs());
let attrs = attrs.append(iattrs.into_thin_attrs());
let hi = self.last_span.hi;
......@@ -3030,7 +3030,7 @@ pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>,
}
let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None));
let (iattrs, body) = try!(self.parse_inner_attrs_and_block());
let attrs = attrs.append_inner(iattrs.into_opt_attrs());
let attrs = attrs.append(iattrs.into_thin_attrs());
let hi = body.span.hi;
return Ok(self.mk_expr(span_lo, hi, ExprWhile(cond, body, opt_ident),
attrs));
......@@ -3045,7 +3045,7 @@ pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>,
try!(self.expect(&token::Eq));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None));
let (iattrs, body) = try!(self.parse_inner_attrs_and_block());
let attrs = attrs.append_inner(iattrs.into_opt_attrs());
let attrs = attrs.append(iattrs.into_thin_attrs());
let hi = body.span.hi;
return Ok(self.mk_expr(span_lo, hi, ExprWhileLet(pat, expr, body, opt_ident), attrs));
}
......@@ -3055,7 +3055,7 @@ pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>,
span_lo: BytePos,
attrs: ThinAttributes) -> PResult<P<Expr>> {
let (iattrs, body) = try!(self.parse_inner_attrs_and_block());
let attrs = attrs.append_inner(iattrs.into_opt_attrs());
let attrs = attrs.append(iattrs.into_thin_attrs());
let hi = body.span.hi;
Ok(self.mk_expr(span_lo, hi, ExprLoop(body, opt_ident), attrs))
}
......@@ -3072,8 +3072,8 @@ fn parse_match_expr(&mut self, attrs: ThinAttributes) -> PResult<P<Expr>> {
}
return Err(e)
}
let attrs = attrs.append_inner(
try!(self.parse_inner_attributes()).into_opt_attrs());
let attrs = attrs.append(
try!(self.parse_inner_attributes()).into_thin_attrs());
let mut arms: Vec<Arm> = Vec::new();
while self.token != token::CloseDelim(token::Brace) {
arms.push(try!(self.parse_arm()));
......@@ -3596,7 +3596,7 @@ fn parse_stmt_(&mut self) -> PResult<Option<Stmt>> {
Ok(Some(if self.check_keyword(keywords::Let) {
try!(self.expect_keyword(keywords::Let));
let decl = try!(self.parse_let(attrs.into_opt_attrs()));
let decl = try!(self.parse_let(attrs.into_thin_attrs()));
let hi = decl.span.hi;
let stmt = StmtDecl(decl, ast::DUMMY_NODE_ID);
spanned(lo, hi, stmt)
......@@ -3654,7 +3654,7 @@ fn parse_stmt_(&mut self) -> PResult<Option<Stmt>> {
hi,
Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })),
style,
attrs.into_opt_attrs());
attrs.into_thin_attrs());
spanned(lo, hi, stmt)
} else {
// if it has a special ident, it's definitely an item
......@@ -3708,7 +3708,7 @@ fn parse_stmt_(&mut self) -> PResult<Option<Stmt>> {
// Remainder are line-expr stmts.
let e = try!(self.parse_expr_res(
Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into_opt_attrs())));
Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into_thin_attrs())));
let hi = e.span.hi;
let stmt = StmtExpr(e, ast::DUMMY_NODE_ID);
spanned(lo, hi, stmt)
......
......@@ -13,7 +13,8 @@
use abi;
use ast::{self, TokenTree};
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
use ast::{ThinAttributesExt, Attribute};
use ast::Attribute;
use attr::ThinAttributesExt;
use ast_util;
use util::parser::AssocOp;
use attr;
......@@ -1638,7 +1639,7 @@ pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
}
ast::StmtMac(ref mac, style, ref attrs) => {
try!(self.space_if_not_bol());
try!(self.print_outer_attributes(attrs.as_attrs()));
try!(self.print_outer_attributes(attrs.as_attr_slice()));
let delim = match style {
ast::MacStmtWithBraces => token::Brace,
_ => token::Paren
......@@ -1983,7 +1984,7 @@ fn print_expr_outer_attr_style(&mut self,
is_inline: bool) -> io::Result<()> {
try!(self.maybe_print_comment(expr.span.lo));
let attrs = expr.attrs.as_attrs();
let attrs = expr.attrs.as_attr_slice();
if is_inline {
try!(self.print_outer_attributes_inline(attrs));
} else {
......@@ -2124,7 +2125,7 @@ fn print_expr_outer_attr_style(&mut self,
ast::ExprBlock(ref blk) => {
try!(self.print_block_unclosed_with_attrs(
&**blk,
i_expr.attrs.as_attrs()));
i_expr.attrs.as_attr_slice()));
}
_ => {
// this is a bare expression
......@@ -2303,7 +2304,7 @@ pub fn print_decl(&mut self, decl: &ast::Decl) -> io::Result<()> {
try!(self.maybe_print_comment(decl.span.lo));
match decl.node {
ast::DeclLocal(ref loc) => {
try!(self.print_outer_attributes(loc.attrs.as_attrs()));
try!(self.print_outer_attributes(loc.attrs.as_attr_slice()));
try!(self.space_if_not_bol());
try!(self.ibox(INDENT_UNIT));
try!(self.word_nbsp("let"));
......
......@@ -25,6 +25,7 @@
use abi::Abi;
use ast::*;
use attr::ThinAttributesExt;
use codemap::Span;
#[derive(Copy, Clone, PartialEq, Eq)]
......@@ -630,7 +631,7 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
}
StmtMac(ref mac, _, ref attrs) => {
visitor.visit_mac(mac);
for attr in attrs.as_attrs() {
for attr in attrs.as_attr_slice() {
visitor.visit_attribute(attr);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册