diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-06-26 02:18:04 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-06-26 02:18:43 +0000 |
| commit | 8eddf0280014972e051856dfe949054acf53c043 (patch) | |
| tree | 8d4523f2bd6a218c75b5a602fa30d5cd85d8184c /src/libsyntax | |
| parent | 8748cd92d06328af657934f6728183c10f92eefe (diff) | |
| parent | 5033eca65f1dd9585aafa9cddd9d4bfd71b820c1 (diff) | |
| download | rust-8eddf0280014972e051856dfe949054acf53c043.tar.gz rust-8eddf0280014972e051856dfe949054acf53c043.zip | |
Rollup merge of #34339 - jseyfried:thin_vec, r=petrochenkov,Manishearth
Generalize and abstract `ThinAttributes` to `ThinVec<Attribute>`.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/attr.rs | 81 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/quote.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/lib.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 157 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/util/thin_vec.rs | 59 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 7 |
14 files changed, 177 insertions, 202 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 51f42a678ce..dcdc1e60a99 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -14,8 +14,8 @@ pub use self::TyParamBound::*; pub use self::UnsafeSource::*; pub use self::ViewPath_::*; pub use self::PathParameters::*; +pub use util::ThinVec; -use attr::ThinAttributes; use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId}; use codemap::{respan, Spanned}; use abi::Abi; @@ -835,10 +835,9 @@ pub enum StmtKind { /// Expr without trailing semi-colon (must have unit type). Expr(P<Expr>), - /// Expr with trailing semi-colon (may have any type). Semi(P<Expr>), - Mac(P<(Mac, MacStmtStyle, ThinAttributes)>), + Mac(P<(Mac, MacStmtStyle, ThinVec<Attribute>)>), } #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -865,7 +864,7 @@ pub struct Local { pub init: Option<P<Expr>>, pub id: NodeId, pub span: Span, - pub attrs: ThinAttributes, + pub attrs: ThinVec<Attribute>, } /// An arm of a 'match'. @@ -913,7 +912,7 @@ pub struct Expr { pub id: NodeId, pub node: ExprKind, pub span: Span, - pub attrs: ThinAttributes + pub attrs: ThinVec<Attribute> } impl fmt::Debug for Expr { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 34d07291bf4..da2967e306f 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -25,6 +25,7 @@ use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use parse::token::InternedString; use parse::{ParseSess, token}; use ptr::P; +use util::ThinVec; use std::cell::{RefCell, Cell}; use std::collections::HashSet; @@ -802,80 +803,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 { fn attrs(&self) -> &[ast::Attribute]; fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self; @@ -890,12 +817,12 @@ impl HasAttrs for Vec<Attribute> { } } -impl HasAttrs for ThinAttributes { +impl HasAttrs for ThinVec<Attribute> { fn attrs(&self) -> &[Attribute] { - self.as_attr_slice() + &self } fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { - self.map_thin_attrs(f) + f(self.into()).into() } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 4a715aa1d5b..757b039fcac 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -380,7 +380,7 @@ impl DummyResult { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Lit(P(codemap::respan(sp, ast::LitKind::Bool(false)))), span: sp, - attrs: None, + attrs: ast::ThinVec::new(), }) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 17655cc1254..f4ae23ed8be 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -530,7 +530,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { init: Some(ex), id: ast::DUMMY_NODE_ID, span: sp, - attrs: None, + attrs: ast::ThinVec::new(), }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -558,7 +558,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { init: Some(ex), id: ast::DUMMY_NODE_ID, span: sp, - attrs: None, + attrs: ast::ThinVec::new(), }); P(ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -601,7 +601,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, node: node, span: span, - attrs: None, + attrs: ast::ThinVec::new(), }) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index ff8d0f81bd0..32635f5cdd2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -15,7 +15,7 @@ use ast; use attr::HasAttrs; use ext::mtwt; use attr; -use attr::{AttrMetaMethods, ThinAttributesExt}; +use attr::AttrMetaMethods; use codemap::{Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use syntax_pos::{self, Span, ExpnId}; use config::StripUnconfigured; @@ -107,7 +107,7 @@ pub fn expand_expr(mut expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> // expr_mac should really be expr_ext or something; it's the // entry-point for all syntax extensions. ast::ExprKind::Mac(mac) => { - return expand_mac_invoc(mac, None, expr.attrs.into_attr_vec(), expr.span, fld); + return expand_mac_invoc(mac, None, expr.attrs.into(), expr.span, fld); } ast::ExprKind::While(cond, body, opt_ident) => { @@ -444,7 +444,7 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> { }; let mut fully_expanded: SmallVector<ast::Stmt> = - expand_mac_invoc(mac, None, attrs.into_attr_vec(), stmt.span, fld); + expand_mac_invoc(mac, None, attrs.into(), stmt.span, fld); // If this is a macro invocation with a semicolon, then apply that // semicolon to the final statement produced by expansion. @@ -1006,7 +1006,7 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> { expr.and_then(|expr| match expr.node { 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)), }) } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 4ffcb295619..3dc7c92f016 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -251,7 +251,7 @@ pub mod rt { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Lit(P(self.clone())), span: DUMMY_SP, - attrs: None, + attrs: ast::ThinVec::new(), }).to_tokens(cx) } } @@ -282,7 +282,7 @@ pub mod rt { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Lit(P(dummy_spanned(lit))), span: DUMMY_SP, - attrs: None, + attrs: ast::ThinVec::new(), }); if *self >= 0 { return lit.to_tokens(cx); @@ -291,7 +291,7 @@ pub mod rt { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Unary(ast::UnOp::Neg, lit), span: DUMMY_SP, - attrs: None, + attrs: ast::ThinVec::new(), }).to_tokens(cx) } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1dc7f45ddbe..b2b286c9b14 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -20,7 +20,6 @@ use ast::*; use ast; -use attr::{ThinAttributes, ThinAttributesExt}; use syntax_pos::Span; use codemap::{Spanned, respan}; use parse::token::{self, keywords}; @@ -332,8 +331,8 @@ pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribut attrs.move_flat_map(|x| fld.fold_attribute(x)) } -pub fn fold_thin_attrs<T: Folder>(attrs: ThinAttributes, fld: &mut T) -> ThinAttributes { - attrs.map_thin_attrs(|v| fold_attrs(v, fld)) +pub fn fold_thin_attrs<T: Folder>(attrs: ThinVec<Attribute>, fld: &mut T) -> ThinVec<Attribute> { + fold_attrs(attrs.into(), fld).into() } pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm { @@ -481,7 +480,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_thin_attrs(|v| fold_attrs(v, fld)), + attrs: fold_attrs(attrs.into(), fld).into(), }) } @@ -1276,7 +1275,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)), }, span: folder.new_span(span), - attrs: attrs.map_thin_attrs(|v| fold_attrs(v, folder)), + attrs: fold_attrs(attrs.into(), folder).into(), } } @@ -1329,9 +1328,7 @@ pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T) StmtKind::Mac(mac) => SmallVector::one(Stmt { id: id, node: StmtKind::Mac(mac.map(|(mac, semi, attrs)| { - let mac = folder.fold_mac(mac); - let attrs = attrs.map_thin_attrs(|attrs| fold_attrs(attrs, folder)); - (mac, semi, attrs) + (folder.fold_mac(mac), semi, fold_attrs(attrs.into(), folder).into()) })), span: span, }) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 9c1b8175a3e..652cf68db07 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -75,6 +75,9 @@ pub mod util { pub mod parser_testing; pub mod small_vector; pub mod move_map; + + mod thin_vec; + pub use self::thin_vec::ThinVec; } pub mod diagnostics { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 28555dc89bc..0c5a672dfbc 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -675,6 +675,7 @@ mod tests { use tokenstream::{self, TokenTree}; 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::ThinVec; // produce a syntax_pos::span fn sp(a: u32, b: u32) -> Span { @@ -696,7 +697,7 @@ mod tests { ), }), span: sp(0, 1), - attrs: None, + attrs: ThinVec::new(), })) } @@ -719,7 +720,7 @@ mod tests { ) }), span: sp(0, 6), - attrs: None, + attrs: ThinVec::new(), })) } @@ -835,10 +836,10 @@ mod tests { ), }), span:sp(7,8), - attrs: None, + attrs: ThinVec::new(), }))), span:sp(0,8), - attrs: None, + attrs: ThinVec::new(), })) } @@ -858,7 +859,7 @@ mod tests { ), }), span: sp(0,1), - attrs: None})), + attrs: ThinVec::new()})), id: ast::DUMMY_NODE_ID, span: sp(0,1)})) @@ -953,7 +954,7 @@ mod tests { ), }), span: sp(17,18), - attrs: None,})), + attrs: ThinVec::new()})), id: ast::DUMMY_NODE_ID, span: sp(17,19)}), expr: None, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c04d2c37157..83401011ed4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -37,7 +37,6 @@ use ast::{TraitItem, TraitRef}; use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; -use attr::{ThinAttributes, ThinAttributesExt, AttributesExt}; use ast::{BinOpKind, UnOp}; use ast; use codemap::{self, CodeMap, Spanned, spanned}; @@ -57,6 +56,7 @@ use print::pprust; use ptr::P; use parse::PResult; use tokenstream::{self, Delimited, SequenceRepetition, TokenTree}; +use util::ThinVec; use std::collections::HashSet; use std::mem; @@ -122,7 +122,7 @@ macro_rules! maybe_whole_expr { _ => unreachable!() }; 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(_)) => { // FIXME: The following avoids an issue with lexical borrowck scopes, @@ -132,7 +132,7 @@ macro_rules! maybe_whole_expr { _ => unreachable!() }; 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 }; @@ -318,12 +318,12 @@ pub struct ModulePathError { pub enum LhsExpr { NotYetParsed, - AttributesParsed(ThinAttributes), + AttributesParsed(ThinVec<Attribute>), AlreadyParsed(P<Expr>), } -impl From<Option<ThinAttributes>> for LhsExpr { - fn from(o: Option<ThinAttributes>) -> Self { +impl From<Option<ThinVec<Attribute>>> for LhsExpr { + fn from(o: Option<ThinVec<Attribute>>) -> Self { if let Some(attrs) = o { LhsExpr::AttributesParsed(attrs) } else { @@ -1703,12 +1703,12 @@ impl<'a> Parser<'a> { let lo = self.span.lo; let literal = P(self.parse_lit()?); 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 { let minus_hi = self.last_span.hi; 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 { Ok(expr) } @@ -2066,13 +2066,13 @@ impl<'a> Parser<'a> { }) } - pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, - node: ExprKind, attrs: ThinAttributes) -> P<Expr> { + pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, node: ExprKind, attrs: ThinVec<Attribute>) + -> P<Expr> { P(Expr { id: ast::DUMMY_NODE_ID, node: node, span: mk_sp(lo, hi), - attrs: attrs, + attrs: attrs.into(), }) } @@ -2129,7 +2129,7 @@ impl<'a> Parser<'a> { } 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 { id: ast::DUMMY_NODE_ID, node: ExprKind::Mac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}), @@ -2138,7 +2138,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 lv_lit = P(codemap::Spanned { node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)), @@ -2179,7 +2179,7 @@ impl<'a> Parser<'a> { // // Therefore, prevent sub-parser from parsing // attributes by giving them a empty "already parsed" list. - let mut attrs = None; + let mut attrs = ThinVec::new(); let lo = self.span.lo; let mut hi = self.span.hi; @@ -2191,9 +2191,7 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Paren) => { self.bump(); - let attrs = self.parse_inner_attributes()? - .into_thin_attrs() - .prepend(attrs); + attrs.extend(self.parse_inner_attributes()?); // (e) is parenthesized e // (e,) is a tuple with only one field, e @@ -2231,9 +2229,7 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Bracket) => { self.bump(); - let inner_attrs = self.parse_inner_attributes()? - .into_thin_attrs(); - attrs.update(|attrs| attrs.append(inner_attrs)); + attrs.extend(self.parse_inner_attributes()?); if self.check(&token::CloseDelim(token::Bracket)) { // Empty vector. @@ -2390,9 +2386,7 @@ impl<'a> Parser<'a> { let mut fields = Vec::new(); let mut base = None; - let attrs = attrs.append( - self.parse_inner_attributes()? - .into_thin_attrs()); + attrs.extend(self.parse_inner_attributes()?); while self.token != token::CloseDelim(token::Brace) { if self.eat(&token::DotDot) { @@ -2459,25 +2453,24 @@ impl<'a> Parser<'a> { } fn parse_or_use_outer_attributes(&mut self, - already_parsed_attrs: Option<ThinAttributes>) - -> PResult<'a, ThinAttributes> { + already_parsed_attrs: Option<ThinVec<Attribute>>) + -> PResult<'a, ThinVec<Attribute>> { if let Some(attrs) = already_parsed_attrs { Ok(attrs) } 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 pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode, - attrs: ThinAttributes) + outer_attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { - let outer_attrs = attrs; self.expect(&token::OpenDelim(token::Brace))?; - let inner_attrs = self.parse_inner_attributes()?.into_thin_attrs(); - let attrs = outer_attrs.append(inner_attrs); + let mut attrs = outer_attrs; + attrs.extend(self.parse_inner_attributes()?); let blk = self.parse_block_tail(lo, blk_mode)?; return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), attrs)); @@ -2485,7 +2478,7 @@ impl<'a> Parser<'a> { /// parse a.b or a(13) or a[4] or just a pub fn parse_dot_or_call_expr(&mut self, - already_parsed_attrs: Option<ThinAttributes>) + already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; @@ -2497,7 +2490,7 @@ impl<'a> Parser<'a> { pub fn parse_dot_or_call_expr_with(&mut self, e0: P<Expr>, lo: BytePos, - attrs: ThinAttributes) + mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { // Stitch the list of outer attributes onto the return value. // A little bit ugly, but the best way given the current code @@ -2505,12 +2498,13 @@ impl<'a> Parser<'a> { self.parse_dot_or_call_expr_with_(e0, lo) .map(|expr| expr.map(|mut expr| { - expr.attrs.update(|a| a.prepend(attrs)); + attrs.extend::<Vec<_>>(expr.attrs.into()); + expr.attrs = attrs; match expr.node { 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... - let span = expr.attrs.as_attr_slice()[0].span; + let span = expr.attrs[0].span; self.span_err(span, "attributes are not yet allowed on `if` \ @@ -2558,7 +2552,7 @@ impl<'a> Parser<'a> { es.insert(0, self_value); let id = spanned(ident_span.lo, ident_span.hi, ident); 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. _ => { @@ -2571,7 +2565,7 @@ impl<'a> Parser<'a> { let id = spanned(ident_span.lo, ident_span.hi, ident); 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()) } }) } @@ -2583,7 +2577,7 @@ impl<'a> Parser<'a> { // expr? while self.eat(&token::Question) { 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 @@ -2611,7 +2605,7 @@ impl<'a> Parser<'a> { Some(n) => { let id = spanned(dot, hi, n); 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 => { let last_span = self.last_span; @@ -2663,7 +2657,7 @@ impl<'a> Parser<'a> { hi = self.last_span.hi; 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[...] @@ -2674,7 +2668,7 @@ impl<'a> Parser<'a> { hi = self.span.hi; self.commit_expr_expecting(&ix, token::CloseDelim(token::Bracket))?; 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) } @@ -2905,7 +2899,7 @@ impl<'a> Parser<'a> { /// Parse a prefix-unary-operator expr pub fn parse_prefix_expr(&mut self, - already_parsed_attrs: Option<ThinAttributes>) + already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let lo = self.span.lo; @@ -2950,8 +2944,7 @@ impl<'a> Parser<'a> { let blk = self.parse_block()?; let span = blk.span; hi = span.hi; - let blk_expr = self.mk_expr(span.lo, span.hi, ExprKind::Block(blk), - None); + let blk_expr = self.mk_expr(span.lo, hi, ExprKind::Block(blk), ThinVec::new()); ExprKind::InPlace(place, blk_expr) } token::Ident(..) if self.token.is_keyword(keywords::Box) => { @@ -2971,7 +2964,7 @@ impl<'a> Parser<'a> { /// This parses an expression accounting for associativity and precedence of the operators in /// the expression. pub fn parse_assoc_expr(&mut self, - already_parsed_attrs: Option<ThinAttributes>) + already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { self.parse_assoc_expr_with(0, already_parsed_attrs.into()) } @@ -3024,13 +3017,13 @@ impl<'a> Parser<'a> { // Special cases: if op == AssocOp::As { let rhs = self.parse_ty()?; - lhs = self.mk_expr(lhs_span.lo, rhs.span.hi, - ExprKind::Cast(lhs, rhs), None); + let (lo, hi) = (lhs_span.lo, rhs.span.hi); + lhs = self.mk_expr(lo, hi, ExprKind::Cast(lhs, rhs), ThinVec::new()); continue } else if op == AssocOp::Colon { let rhs = self.parse_ty()?; - lhs = self.mk_expr(lhs_span.lo, rhs.span.hi, - ExprKind::Type(lhs, rhs), None); + let (lo, hi) = (lhs_span.lo, rhs.span.hi); + lhs = self.mk_expr(lo, hi, ExprKind::Type(lhs, rhs), ThinVec::new()); continue } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot { // If we didn’t have to handle `x..`/`x...`, it would be pretty easy to @@ -3056,7 +3049,7 @@ impl<'a> Parser<'a> { }; 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 } @@ -3083,6 +3076,7 @@ impl<'a> Parser<'a> { }), }?; + let (lo, hi) = (lhs_span.lo, rhs.span.hi); lhs = match op { AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor | @@ -3090,14 +3084,13 @@ impl<'a> Parser<'a> { AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual | AssocOp::Greater | AssocOp::GreaterEqual => { 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); - self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None) + self.mk_expr(lo, hi, binary, ThinVec::new()) } 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 => - 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) => { let aop = match k { token::Plus => BinOpKind::Add, @@ -3111,9 +3104,8 @@ impl<'a> Parser<'a> { token::Shl => BinOpKind::Shl, 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); - 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 => { self.bug("As, Colon, DotDot or DotDotDot branch reached") @@ -3148,7 +3140,7 @@ impl<'a> Parser<'a> { /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr` fn parse_prefix_range_expr(&mut self, - already_parsed_attrs: Option<ThinAttributes>) + already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot); let tok = self.token.clone(); @@ -3193,7 +3185,7 @@ impl<'a> Parser<'a> { } /// 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) { return self.parse_if_let_expr(attrs); } @@ -3211,7 +3203,7 @@ impl<'a> Parser<'a> { } /// 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>> { let lo = self.last_span.lo; self.expect_keyword(keywords::Let)?; @@ -3232,7 +3224,7 @@ impl<'a> Parser<'a> { pub fn parse_lambda_expr(&mut self, lo: BytePos, capture_clause: CaptureBy, - attrs: ThinAttributes) + attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { let decl = self.parse_fn_block_decl()?; @@ -3267,24 +3259,24 @@ impl<'a> Parser<'a> { // `else` token already eaten pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { if self.eat_keyword(keywords::If) { - return self.parse_if_expr(None); + return self.parse_if_expr(ThinVec::new()); } else { 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) pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, 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>` let pat = self.parse_pat()?; self.expect_keyword(keywords::In)?; let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; 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; @@ -3296,13 +3288,13 @@ impl<'a> Parser<'a> { /// Parse a 'while' or 'while let' expression ('while' token already eaten) pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, span_lo: BytePos, - attrs: ThinAttributes) -> PResult<'a, P<Expr>> { + mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { if self.token.is_keyword(keywords::Let) { return self.parse_while_let_expr(opt_ident, span_lo, attrs); } let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; 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; return Ok(self.mk_expr(span_lo, hi, ExprKind::While(cond, body, opt_ident), attrs)); @@ -3311,13 +3303,13 @@ impl<'a> Parser<'a> { /// Parse a 'while let' expression ('while' token already eaten) pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, span_lo: BytePos, - attrs: ThinAttributes) -> PResult<'a, P<Expr>> { + mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { self.expect_keyword(keywords::Let)?; let pat = self.parse_pat()?; self.expect(&token::Eq)?; let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; 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; return Ok(self.mk_expr(span_lo, hi, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs)); } @@ -3325,15 +3317,15 @@ impl<'a> Parser<'a> { // parse `loop {...}`, `loop` token already eaten pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, 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 attrs = attrs.append(iattrs.into_thin_attrs()); + attrs.extend(iattrs); let hi = body.span.hi; Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs)) } // `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 lo = self.last_span.lo; let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, @@ -3345,8 +3337,8 @@ impl<'a> Parser<'a> { } return Err(e) } - let attrs = attrs.append( - self.parse_inner_attributes()?.into_thin_attrs()); + attrs.extend(self.parse_inner_attributes()?); + let mut arms: Vec<Arm> = Vec::new(); while self.token != token::CloseDelim(token::Brace) { match self.parse_arm() { @@ -3419,7 +3411,7 @@ impl<'a> Parser<'a> { /// Parse an expression, subject to the given 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>> { self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs)) } @@ -3617,7 +3609,7 @@ impl<'a> Parser<'a> { (None, self.parse_path(PathStyle::Expr)?) }; 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 { self.parse_pat_literal_maybe_minus() } @@ -3712,7 +3704,8 @@ impl<'a> Parser<'a> { token::DotDotDot => { // Parse range 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(); let end = self.parse_pat_range_end()?; pat = PatKind::Range(begin, end); @@ -3807,7 +3800,7 @@ impl<'a> Parser<'a> { } /// 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 pat = self.parse_pat()?; @@ -3941,7 +3934,7 @@ impl<'a> Parser<'a> { Ok(Some(if self.eat_keyword(keywords::Let) { Stmt { id: ast::DUMMY_NODE_ID, - node: StmtKind::Local(self.parse_local(attrs.into_thin_attrs())?), + node: StmtKind::Local(self.parse_local(attrs.into())?), span: mk_sp(lo, self.last_span.hi), } } else if self.token.is_ident() @@ -3997,7 +3990,7 @@ impl<'a> Parser<'a> { let mac = spanned(lo, hi, Mac_ { path: pth, tts: tts }); Stmt { id: ast::DUMMY_NODE_ID, - node: StmtKind::Mac(P((mac, style, attrs.into_thin_attrs()))), + node: StmtKind::Mac(P((mac, style, attrs.into()))), span: mk_sp(lo, hi), } } else { @@ -4057,7 +4050,7 @@ impl<'a> Parser<'a> { // Remainder are line-expr stmts. let e = self.parse_expr_res( - Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into_thin_attrs()))?; + Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into()))?; Stmt { id: ast::DUMMY_NODE_ID, span: mk_sp(lo, e.span.hi), @@ -4150,7 +4143,7 @@ impl<'a> Parser<'a> { } fn handle_macro_in_block(&mut self, - (mac, style, attrs): (ast::Mac, MacStmtStyle, ThinAttributes), + (mac, style, attrs): (ast::Mac, MacStmtStyle, ThinVec<Attribute>), span: Span, stmts: &mut Vec<Stmt>, last_block_expr: &mut Option<P<Expr>>) @@ -4168,7 +4161,7 @@ impl<'a> Parser<'a> { self.bump(); } _ => { - let e = self.mk_mac_expr(span.lo, span.hi, mac.node, None); + let e = self.mk_mac_expr(span.lo, span.hi, mac.node, ThinVec::new()); let lo = e.span.lo; let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a268a6e9605..d399f538004 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -14,7 +14,6 @@ use abi::{self, Abi}; use ast::{self, BlockCheckMode, PatKind}; use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Attribute; -use attr::ThinAttributesExt; use util::parser::AssocOp; use attr; use attr::{AttrMetaMethods, AttributeMethods}; @@ -1607,7 +1606,7 @@ impl<'a> State<'a> { try!(self.maybe_print_comment(st.span.lo)); match st.node { ast::StmtKind::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.ibox(INDENT_UNIT)); try!(self.word_nbsp("let")); @@ -1635,7 +1634,7 @@ impl<'a> State<'a> { ast::StmtKind::Mac(ref mac) => { let (ref mac, style, ref attrs) = **mac; 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 { ast::MacStmtStyle::Braces => token::Brace, _ => token::Paren @@ -1975,7 +1974,7 @@ impl<'a> State<'a> { is_inline: bool) -> io::Result<()> { try!(self.maybe_print_comment(expr.span.lo)); - let attrs = expr.attrs.as_attr_slice(); + let attrs = &expr.attrs; if is_inline { try!(self.print_outer_attributes_inline(attrs)); } else { @@ -2119,9 +2118,7 @@ impl<'a> State<'a> { let i_expr = body.expr.as_ref().unwrap(); match i_expr.node { ast::ExprKind::Block(ref blk) => { - try!(self.print_block_unclosed_with_attrs( - &blk, - i_expr.attrs.as_attr_slice())); + try!(self.print_block_unclosed_with_attrs(&blk, &i_expr.attrs)); } _ => { // this is a bare expression diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index cc3fff09617..078103f834a 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -608,10 +608,10 @@ fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> { mk_test_desc_and_fn_rec(cx, test) }).collect()), span: DUMMY_SP, - attrs: None, + attrs: ast::ThinVec::new(), })), span: DUMMY_SP, - attrs: None, + attrs: ast::ThinVec::new(), }) } diff --git a/src/libsyntax/util/thin_vec.rs b/src/libsyntax/util/thin_vec.rs new file mode 100644 index 00000000000..546686b46b8 --- /dev/null +++ b/src/libsyntax/util/thin_vec.rs @@ -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(), + } + } +} diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index aca0c2bcf57..571965ef872 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -25,7 +25,6 @@ use abi::Abi; use ast::*; -use attr::ThinAttributesExt; use syntax_pos::Span; use codemap::Spanned; @@ -184,7 +183,7 @@ pub fn walk_mod<V: Visitor>(visitor: &mut V, module: &Mod) { } pub fn walk_local<V: Visitor>(visitor: &mut V, local: &Local) { - for attr in local.attrs.as_attr_slice() { + for attr in local.attrs.iter() { visitor.visit_attribute(attr); } visitor.visit_pat(&local.pat); @@ -604,7 +603,7 @@ pub fn walk_stmt<V: Visitor>(visitor: &mut V, statement: &Stmt) { StmtKind::Mac(ref mac) => { let (ref mac, _, ref attrs) = **mac; visitor.visit_mac(mac); - for attr in attrs.as_attr_slice() { + for attr in attrs.iter() { visitor.visit_attribute(attr); } } @@ -616,7 +615,7 @@ pub fn walk_mac<V: Visitor>(_: &mut V, _: &Mac) { } pub fn walk_expr<V: Visitor>(visitor: &mut V, expression: &Expr) { - for attr in expression.attrs.as_attr_slice() { + for attr in expression.attrs.iter() { visitor.visit_attribute(attr); } match expression.node { |
