diff --git a/src/librustc/hir/fold.rs b/src/librustc/hir/fold.rs index 1e80bc3c54dd0..06275efc5f85a 100644 --- a/src/librustc/hir/fold.rs +++ b/src/librustc/hir/fold.rs @@ -14,7 +14,6 @@ use hir::*; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem}; use syntax::ast::MetaItemKind; -use syntax::attr::ThinAttributesExt; use hir; use syntax::codemap::{respan, Span, Spanned}; use syntax::ptr::P; @@ -292,8 +291,11 @@ pub fn noop_fold_view_path(view_path: P, fld: &mut T) -> P< }) } -pub fn fold_attrs(attrs: HirVec, fld: &mut T) -> HirVec { - attrs.move_flat_map(|x| fld.fold_attribute(x)) +pub fn fold_attrs(attrs: T, fld: &mut F) -> T + where T: Into> + From>, + F: Folder, +{ + attrs.into().move_flat_map(|x| fld.fold_attribute(x)).into() } pub fn noop_fold_arm(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm { @@ -461,7 +463,7 @@ pub fn noop_fold_local(l: P, fld: &mut T) -> P { pat: fld.fold_pat(pat), init: init.map(|e| fld.fold_expr(e)), 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(Expr { id, node, span, attrs }: Expr, folder: & } }, span: folder.new_span(span), - attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs.into(), folder).into()), + attrs: fold_attrs(attrs, folder), } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index d47de676e7960..b677594d6f80d 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -27,7 +27,6 @@ use syntax::abi::Abi; use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute}; -use syntax::attr::ThinAttributesExt; use syntax::codemap::{Span, Spanned}; 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); } 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, body, expression.span, diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 393045bf93efb..b7689a832fc26 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,7 +50,6 @@ use session::Session; use std::collections::BTreeMap; use std::iter; use syntax::ast::*; -use syntax::attr::{ThinAttributes, ThinAttributesExt}; use syntax::ptr::P; use syntax::codemap::{respan, Spanned, Span}; use syntax::parse::token; @@ -962,16 +961,16 @@ impl<'a> LoweringContext<'a> { let make_call = |this: &mut LoweringContext, p, args| { let path = this.core_path(e.span, p); - let path = this.expr_path(path, None); - this.expr_call(e.span, path, args, None) + let path = this.expr_path(path, ThinVec::new()); + this.expr_call(e.span, path, args) }; 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| { - this.stmt_let(e.span, true, bind, expr, None) + this.stmt_let(e.span, true, bind, expr) }; // let placer = ; @@ -980,21 +979,21 @@ impl<'a> LoweringContext<'a> { placer_expr, e.span, hir::PopUnstableBlock, - None); + ThinVec::new()); mk_stmt_let(self, placer_ident, placer_expr) }; // let mut place = Placer::make_place(placer); 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]); mk_stmt_let_mut(self, place_ident, call) }; // let p_ptr = Place::pointer(&mut place); let (s3, p_ptr_binding) = { - let agent = self.expr_ident(e.span, place_ident, None, place_binding); - let args = hir_vec![self.expr_mut_addr_of(e.span, agent, None)]; + let agent = self.expr_ident(e.span, place_ident, place_binding); + let args = hir_vec![self.expr_mut_addr_of(e.span, agent)]; let call = make_call(self, &place_pointer, args); mk_stmt_let(self, p_ptr_ident, call) }; @@ -1005,11 +1004,12 @@ impl<'a> LoweringContext<'a> { value_expr, e.span, hir::PopUnstableBlock, - None); + ThinVec::new()); self.signal_block_expr(hir_vec![], value_expr, e.span, - hir::PopUnsafeBlock(hir::CompilerGenerated), None) + hir::PopUnsafeBlock(hir::CompilerGenerated), + ThinVec::new()) }; // push_unsafe!({ @@ -1017,19 +1017,20 @@ impl<'a> LoweringContext<'a> { // InPlace::finalize(place) // }) 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 = hir::StmtSemi( make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), self.next_id()); 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]); self.signal_block_expr(hir_vec![call_move_val_init], call, e.span, - hir::PushUnsafeBlock(hir::CompilerGenerated), None) + hir::PushUnsafeBlock(hir::CompilerGenerated), + ThinVec::new()) }; return self.signal_block_expr(hir_vec![s1, s2, s3], @@ -1101,7 +1102,7 @@ impl<'a> LoweringContext<'a> { rules: hir::DefaultBlock, span: span, }); - self.expr_block(blk, None) + self.expr_block(blk, ThinVec::new()) } _ => self.lower_expr(els), } @@ -1168,7 +1169,7 @@ impl<'a> LoweringContext<'a> { expr, e.span, hir::PopUnstableBlock, - None); + ThinVec::new()); this.field(token::intern(s), signal_block, ast_expr.span) }).collect(); let attrs = ast_expr.attrs.clone(); @@ -1180,7 +1181,7 @@ impl<'a> LoweringContext<'a> { hir_expr, ast_expr.span, hir::PushUnstableBlock, - None) + ThinVec::new()) } use syntax::ast::RangeLimits::*; @@ -1267,9 +1268,9 @@ impl<'a> LoweringContext<'a> { ex.span = e.span; } // merge attributes into the inner expression. - ex.attrs.update(|attrs| { - attrs.prepend(e.attrs.clone()) - }); + let mut attrs = e.attrs.clone(); + attrs.extend::>(ex.attrs.into()); + ex.attrs = attrs; ex }); } @@ -1288,7 +1289,7 @@ impl<'a> LoweringContext<'a> { // ` => ` let pat_arm = { 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); self.arm(hir_vec![pat], body_expr) }; @@ -1308,7 +1309,7 @@ impl<'a> LoweringContext<'a> { attrs: hir_vec![], pats: hir_vec![pat_under], guard: Some(cond), - body: self.expr_block(then, None), + body: self.expr_block(then, ThinVec::new()), }); else_opt.map(|else_opt| (else_opt, true)) } @@ -1339,7 +1340,7 @@ impl<'a> LoweringContext<'a> { let else_arm = { let pat_under = self.pat_wild(e.span); 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) }; @@ -1374,7 +1375,7 @@ impl<'a> LoweringContext<'a> { // ` => ` let pat_arm = { 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); self.arm(hir_vec![pat], body_expr) }; @@ -1382,7 +1383,7 @@ impl<'a> LoweringContext<'a> { // `_ => break` let break_arm = { 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) }; @@ -1393,7 +1394,7 @@ impl<'a> LoweringContext<'a> { hir::ExprMatch(sub_expr, arms, hir::MatchSource::WhileLetDesugar), - None); + ThinVec::new()); // `[opt_ident]: loop { ... }` let loop_block = self.block_expr(match_expr); @@ -1435,7 +1436,7 @@ impl<'a> LoweringContext<'a> { id: self.next_id(), node: hir::ExprBlock(body_block), span: body_span, - attrs: None, + attrs: ThinVec::new(), }); let pat = self.lower_pat(pat); let some_pat = self.pat_some(e.span, pat); @@ -1445,7 +1446,7 @@ impl<'a> LoweringContext<'a> { // `::std::option::Option::None => break` 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); self.arm(hir_vec![pat], break_expr) }; @@ -1461,25 +1462,26 @@ impl<'a> LoweringContext<'a> { self.path_global(e.span, strs) }; - let iter = self.expr_ident(e.span, iter, None, iter_pat.id); - let ref_mut_iter = self.expr_mut_addr_of(e.span, iter, None); - let next_path = self.expr_path(next_path, None); - let next_expr = self.expr_call(e.span, - next_path, - hir_vec![ref_mut_iter], - None); + let iter = self.expr_ident(e.span, iter, iter_pat.id); + let ref_mut_iter = self.expr_mut_addr_of(e.span, iter); + let next_path = self.expr_path(next_path, ThinVec::new()); + let next_expr = self.expr_call(e.span, next_path, hir_vec![ref_mut_iter]); let arms = hir_vec![pat_arm, break_arm]; self.expr(e.span, hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), - None) + ThinVec::new()) }; // `[opt_ident]: loop { ... }` 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 = - P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None }); + let loop_expr = P(hir::Expr { + id: e.id, + node: loop_expr, + span: e.span, + attrs: ThinVec::new(), + }); // `mut iter => { ... }` 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) }; - let into_iter = self.expr_path(into_iter_path, None); - self.expr_call(e.span, into_iter, hir_vec![head], None) + let into_iter = self.expr_path(into_iter_path, ThinVec::new()); + self.expr_call(e.span, into_iter, hir_vec![head]) }; let match_expr = self.expr_match(e.span, into_iter_expr, hir_vec![iter_arm], - hir::MatchSource::ForLoopDesugar, - None); + hir::MatchSource::ForLoopDesugar); // `{ let _result = ...; _result }` // underscore prevents an unused_variables lint if the head diverges let result_ident = self.str_to_ident("_result"); 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)); // add the attributes to the outer returned expr node return self.expr_block(block, e.attrs.clone()); @@ -1535,7 +1536,7 @@ impl<'a> LoweringContext<'a> { let ok_arm = { let val_ident = self.str_to_ident("val"); 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); self.arm(hir_vec![ok_pat], val_expr) @@ -1548,26 +1549,26 @@ impl<'a> LoweringContext<'a> { let from_expr = { let path = self.std_path(&["convert", "From", "from"]); let path = self.path_global(e.span, path); - let from = self.expr_path(path, None); - let err_expr = self.expr_ident(e.span, err_ident, None, err_local.id); + let from = self.expr_path(path, ThinVec::new()); + 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 path = self.std_path(&["result", "Result", "Err"]); let path = self.path_global(e.span, path); - let err_ctor = self.expr_path(path, None); - self.expr_call(e.span, err_ctor, hir_vec![from_expr], None) + let err_ctor = self.expr_path(path, ThinVec::new()); + self.expr_call(e.span, err_ctor, hir_vec![from_expr]) }; let err_pat = self.pat_err(e.span, err_local); 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) }; 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"), @@ -1682,23 +1683,18 @@ impl<'a> LoweringContext<'a> { } } - fn expr_break(&mut self, span: Span, attrs: ThinAttributes) -> P { + fn expr_break(&mut self, span: Span, attrs: ThinVec) -> P { self.expr(span, hir::ExprBreak(None), attrs) } - fn expr_call(&mut self, - span: Span, - e: P, - args: hir::HirVec>, - attrs: ThinAttributes) + fn expr_call(&mut self, span: Span, e: P, args: hir::HirVec>) -> P { - 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) - -> P { + fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> P { 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| { Def::Local(defs.local_def_id(binding), binding) @@ -1708,12 +1704,11 @@ impl<'a> LoweringContext<'a> { expr } - fn expr_mut_addr_of(&mut self, span: Span, e: P, attrs: ThinAttributes) - -> P { - self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), attrs) + fn expr_mut_addr_of(&mut self, span: Span, e: P) -> P { + self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new()) } - fn expr_path(&mut self, path: hir::Path, attrs: ThinAttributes) -> P { + fn expr_path(&mut self, path: hir::Path, attrs: ThinVec) -> P { let def = self.resolver.resolve_generated_global_path(&path, true); let expr = self.expr(path.span, hir::ExprPath(None, path), attrs); self.resolver.record_resolution(expr.id, def); @@ -1724,19 +1719,17 @@ impl<'a> LoweringContext<'a> { span: Span, arg: P, arms: hir::HirVec, - source: hir::MatchSource, - attrs: ThinAttributes) + source: hir::MatchSource) -> P { - 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, attrs: ThinAttributes) -> P { + fn expr_block(&mut self, b: P, attrs: ThinVec) -> P { self.expr(b.span, hir::ExprBlock(b), attrs) } - fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec>, attrs: ThinAttributes) - -> P { - self.expr(sp, hir::ExprTup(exprs), attrs) + fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec>) -> P { + self.expr(sp, hir::ExprTup(exprs), ThinVec::new()) } fn expr_struct(&mut self, @@ -1744,14 +1737,14 @@ impl<'a> LoweringContext<'a> { path: hir::Path, fields: hir::HirVec, e: Option>, - attrs: ThinAttributes) -> P { + attrs: ThinVec) -> P { let def = self.resolver.resolve_generated_global_path(&path, false); let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs); self.resolver.record_resolution(expr.id, def); expr } - fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinAttributes) -> P { + fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec) -> P { P(hir::Expr { id: self.next_id(), node: node, @@ -1760,12 +1753,7 @@ impl<'a> LoweringContext<'a> { }) } - fn stmt_let(&mut self, - sp: Span, - mutbl: bool, - ident: Name, - ex: P, - attrs: ThinAttributes) + fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P) -> (hir::Stmt, NodeId) { let pat = if mutbl { self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable)) @@ -1779,7 +1767,7 @@ impl<'a> LoweringContext<'a> { init: Some(ex), id: self.next_id(), span: sp, - attrs: attrs, + attrs: ThinVec::new(), }); let decl = respan(sp, hir::DeclLocal(local)); (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id) @@ -1939,7 +1927,7 @@ impl<'a> LoweringContext<'a> { expr: P, span: Span, rule: hir::BlockCheckMode, - attrs: ThinAttributes) + attrs: ThinVec) -> P { let id = self.next_id(); let block = P(hir::Block { diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index bac96c68e4cf8..ec23020eecb6b 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -27,7 +27,6 @@ use hir::map::{self, Node}; use syntax::abi; use hir::{Block, FnDecl}; use syntax::ast::{Attribute, Name, NodeId}; -use syntax::attr::ThinAttributesExt; use hir as ast; use syntax::codemap::Span; use hir::intravisit::FnKind; @@ -257,11 +256,7 @@ impl<'a> FnLikeNode<'a> { } map::NodeExpr(e) => match e.node { ast::ExprClosure(_, ref decl, ref block, _fn_decl_span) => - closure(ClosureParts::new(&decl, - &block, - e.id, - e.span, - e.attrs.as_attr_slice())), + closure(ClosureParts::new(&decl, &block, e.id, e.span, &e.attrs)), _ => bug!("expr FnLikeNode that is not fn-like"), }, _ => bug!("other FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 41b72e569f475..cf54c89b354d4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -23,7 +23,6 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, }; -use syntax::attr::ThinAttributesExt; use syntax::codemap::{Span, Spanned}; use syntax::visit; @@ -577,7 +576,7 @@ impl<'ast> Map<'ast> { Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]), Some(NodeImplItem(ref ii)) => Some(&ii.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()), // unit/tuple structs take the attributes straight from // the struct definition. diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 8faa1cc1174e8..d3576588aef8f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -40,9 +40,9 @@ use syntax::codemap::{self, mk_sp, respan, Span, Spanned, ExpnId}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; -use syntax::attr::{ThinAttributes, ThinAttributesExt}; use syntax::parse::token::{keywords, InternedString}; use syntax::ptr::P; +use syntax::util::ThinVec; use std::collections::BTreeMap; use std::fmt; @@ -732,7 +732,7 @@ impl Stmt_ { match *self { StmtDecl(ref d, _) => d.node.attrs(), 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>, pub id: NodeId, pub span: Span, - pub attrs: ThinAttributes, + pub attrs: ThinVec, } pub type Decl = Spanned; @@ -772,7 +772,7 @@ pub enum Decl_ { impl Decl_ { pub fn attrs(&self) -> &[Attribute] { match *self { - DeclLocal(ref l) => l.attrs.as_attr_slice(), + DeclLocal(ref l) => &l.attrs, DeclItem(_) => &[] } } @@ -817,7 +817,7 @@ pub struct Expr { pub id: NodeId, pub node: Expr_, pub span: Span, - pub attrs: ThinAttributes, + pub attrs: ThinVec, } impl fmt::Debug for Expr { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 94f17ea779ac8..7d8a3b45bdbda 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -44,7 +44,6 @@ use syntax::codemap::Span; use syntax::errors::DiagnosticBuilder; use syntax::parse::token::InternedString; use syntax::ast; -use syntax::attr::ThinAttributesExt; use hir; use hir::intravisit as hir_visit; 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) { - 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); 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) { - 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); 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) { - 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); 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) { - 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); ast_visit::walk_local(cx, l); }) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index dbca15ffd34b9..c486c282b2f4b 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -451,7 +451,7 @@ fn const_val_to_expr(value: &ConstVal) -> P { id: 0, node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })), span: DUMMY_SP, - attrs: None, + attrs: ast::ThinVec::new(), }) } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 0a093887c5094..4a7f38dd66be4 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -672,7 +672,7 @@ impl fold::Folder for ReplaceBodyWithLoop { node: ast::ExprKind::Loop(empty_block, None), id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP, - attrs: None, + attrs: ast::ThinVec::new(), }); expr_to_block(b.rules, Some(loop_expr)) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8537fcc221c95..7fe7021742483 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -14,8 +14,9 @@ pub use self::TyParamBound::*; pub use self::UnsafeSource::*; pub use self::ViewPath_::*; 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 abi::Abi; use errors; @@ -809,7 +810,7 @@ pub enum StmtKind { /// Expr with trailing semi-colon (may have any type): Semi(P, NodeId), - Mac(P, MacStmtStyle, ThinAttributes), + Mac(P, MacStmtStyle, ThinVec), } impl StmtKind { @@ -851,7 +852,7 @@ pub struct Local { pub init: Option>, pub id: NodeId, pub span: Span, - pub attrs: ThinAttributes, + pub attrs: ThinVec, } impl Local { @@ -912,7 +913,7 @@ pub struct Expr { pub id: NodeId, pub node: ExprKind, pub span: Span, - pub attrs: ThinAttributes + pub attrs: ThinVec } impl Expr { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index e36e15802f0ae..200df680ca676 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -26,6 +26,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; @@ -803,80 +804,6 @@ impl IntType { } } -/// A list of attributes, behind a optional box as -/// a space optimization. -pub type ThinAttributes = Option>>; - -pub trait ThinAttributesExt { - fn map_thin_attrs(self, f: F) -> Self - where F: FnOnce(Vec) -> Vec; - fn prepend(mut self, attrs: Self) -> Self; - fn append(mut self, attrs: Self) -> Self; - fn update(&mut self, f: F) - where Self: Sized, - F: FnOnce(Self) -> Self; - fn as_attr_slice(&self) -> &[Attribute]; - fn into_attr_vec(self) -> Vec; -} - -impl ThinAttributesExt for ThinAttributes { - fn map_thin_attrs(self, f: F) -> Self - where F: FnOnce(Vec) -> Vec - { - 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(&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 { - match self { - Some(b) => *b, - None => Vec::new(), - } - } -} - -pub trait AttributesExt { - fn into_thin_attrs(self) -> ThinAttributes; -} - -impl AttributesExt for Vec { - 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) -> Vec>(self, f: F) -> Self; @@ -885,13 +812,13 @@ pub trait HasAttrs: Sized { /// A cheap way to add Attributes to an AST node. pub trait WithAttrs { // FIXME: Could be extended to anything IntoIter - fn with_attrs(self, attrs: ThinAttributes) -> Self; + fn with_attrs(self, attrs: ThinVec) -> Self; } impl WithAttrs for T { - fn with_attrs(self, attrs: ThinAttributes) -> Self { + fn with_attrs(self, attrs: ThinVec) -> Self { self.map_attrs(|mut orig_attrs| { - orig_attrs.extend(attrs.into_attr_vec()); + orig_attrs.extend::>(attrs.into()); orig_attrs }) } @@ -906,12 +833,12 @@ impl HasAttrs for Vec { } } -impl HasAttrs for ThinAttributes { +impl HasAttrs for ThinVec { fn attrs(&self) -> &[Attribute] { - self.as_attr_slice() + &self } fn map_attrs) -> Vec>(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 4f700e9170fc8..bc9f0c1776a16 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -350,7 +350,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 3a1cdae9bfbd0..8693b3b8684e1 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -525,7 +525,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { init: Some(ex), id: ast::DUMMY_NODE_ID, span: sp, - attrs: None, + attrs: ast::ThinVec::new(), }); let decl = respan(sp, ast::DeclKind::Local(local)); respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)) @@ -550,7 +550,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { init: Some(ex), id: ast::DUMMY_NODE_ID, span: sp, - attrs: None, + attrs: ast::ThinVec::new(), }); let decl = respan(sp, ast::DeclKind::Local(local)); 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, 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 ed419d94ee43d..20a5ff932b308 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -16,7 +16,7 @@ use ast; use ext::mtwt; use ext::build::AstBuilder; use attr; -use attr::{AttrMetaMethods, WithAttrs, ThinAttributesExt}; +use attr::{AttrMetaMethods, WithAttrs}; use codemap; use codemap::{Span, Spanned, ExpnInfo, ExpnId, NameAndSpan, MacroBang, MacroAttribute}; use config::StripUnconfigured; @@ -104,7 +104,7 @@ pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P { // expr_mac should really be expr_ext or something; it's the // entry-point for all syntax extensions. 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) => { @@ -449,7 +449,7 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector { }; let mut fully_expanded: SmallVector = - 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 // 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) -> Option> { 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 871b0d4b1c023..58143075e69af 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -250,7 +250,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) } } @@ -281,7 +281,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); @@ -290,7 +290,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 edf418e33325b..11b835d9455fc 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -20,7 +20,6 @@ use ast::*; use ast; -use attr::{ThinAttributes, ThinAttributesExt}; use codemap::{respan, Span, Spanned}; use parse::token::{self, keywords}; use ptr::P; @@ -336,8 +335,8 @@ pub fn fold_attrs(attrs: Vec, fld: &mut T) -> Vec(attrs: ThinAttributes, fld: &mut T) -> ThinAttributes { - attrs.map_thin_attrs(|v| fold_attrs(v, fld)) +pub fn fold_thin_attrs(attrs: ThinVec, fld: &mut T) -> ThinVec { + fold_attrs(attrs.into(), fld).into() } pub fn noop_fold_arm(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm { @@ -498,7 +497,7 @@ pub fn noop_fold_local(l: P, fld: &mut T) -> P { 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(), }) } @@ -1300,7 +1299,7 @@ pub fn noop_fold_expr(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(), } } @@ -1348,7 +1347,7 @@ pub fn noop_fold_stmt(Spanned {node, span}: Stmt, folder: &mut T) StmtKind::Mac(mac, semi, attrs) => SmallVector::one(Spanned { node: StmtKind::Mac(mac.map(|m| folder.fold_mac(m)), semi, - attrs.map_thin_attrs(|v| fold_attrs(v, folder))), + fold_attrs(attrs.into(), folder).into()), span: span }) } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 420a41e03b914..af13f92239745 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -73,6 +73,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 2e4d46bc98318..f72fb0dedf86a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -672,6 +672,7 @@ mod tests { use ptr::P; 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 codemap::span fn sp(a: u32, b: u32) -> Span { @@ -693,7 +694,7 @@ mod tests { ), }), span: sp(0, 1), - attrs: None, + attrs: ThinVec::new(), })) } @@ -716,7 +717,7 @@ mod tests { ) }), span: sp(0, 6), - attrs: None, + attrs: ThinVec::new(), })) } @@ -832,10 +833,10 @@ mod tests { ), }), span:sp(7,8), - attrs: None, + attrs: ThinVec::new(), }))), span:sp(0,8), - attrs: None, + attrs: ThinVec::new(), })) } @@ -855,7 +856,7 @@ mod tests { ), }), span: sp(0,1), - attrs: None}), + attrs: ThinVec::new()}), ast::DUMMY_NODE_ID), span: sp(0,1)})) @@ -950,7 +951,7 @@ mod tests { ), }), span: sp(17,18), - attrs: None,}), + attrs: ThinVec::new(),}), 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 341b076e7cf30..827d3f32c01fe 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -37,7 +37,6 @@ use ast::{Delimited, SequenceRepetition, TokenTree, 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, Span, BytePos, Spanned, spanned, mk_sp, CodeMap}; @@ -55,6 +54,7 @@ use util::parser::{AssocOp, Fixity}; use print::pprust; use ptr::P; use parse::PResult; +use util::ThinVec; use std::collections::HashSet; use std::mem; @@ -120,7 +120,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, @@ -130,7 +130,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 }; @@ -316,12 +316,12 @@ pub struct ModulePathError { pub enum LhsExpr { NotYetParsed, - AttributesParsed(ThinAttributes), + AttributesParsed(ThinVec), AlreadyParsed(P), } -impl From> for LhsExpr { - fn from(o: Option) -> Self { +impl From>> for LhsExpr { + fn from(o: Option>) -> Self { if let Some(attrs) = o { LhsExpr::AttributesParsed(attrs) } else { @@ -1676,12 +1676,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) } @@ -2039,13 +2039,13 @@ impl<'a> Parser<'a> { }) } - pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, - node: ExprKind, attrs: ThinAttributes) -> P { + pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, node: ExprKind, attrs: ThinVec) + -> P { P(Expr { id: ast::DUMMY_NODE_ID, node: node, 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, - m: Mac_, attrs: ThinAttributes) -> P { + m: Mac_, attrs: ThinVec) -> P { P(Expr { id: ast::DUMMY_NODE_ID, 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 { + pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinVec) -> P { let span = &self.span; let lv_lit = P(codemap::Spanned { 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 // 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; @@ -2164,9 +2164,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 @@ -2204,9 +2202,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. @@ -2363,9 +2359,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) { @@ -2432,25 +2426,24 @@ impl<'a> Parser<'a> { } fn parse_or_use_outer_attributes(&mut self, - already_parsed_attrs: Option) - -> PResult<'a, ThinAttributes> { + already_parsed_attrs: Option>) + -> PResult<'a, ThinVec> { 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) -> PResult<'a, P> { - 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)); @@ -2458,7 +2451,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) + already_parsed_attrs: Option>) -> PResult<'a, P> { 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, e0: P, lo: BytePos, - attrs: ThinAttributes) + mut attrs: ThinVec) -> PResult<'a, P> { // Stitch the list of outer attributes onto the return value. // 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) .map(|expr| expr.map(|mut expr| { - expr.attrs.update(|a| a.prepend(attrs)); + attrs.extend::>(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` \ @@ -2531,7 +2525,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. _ => { @@ -2544,7 +2538,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()) } }) } @@ -2556,7 +2550,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 @@ -2584,7 +2578,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; @@ -2636,7 +2630,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[...] @@ -2647,7 +2641,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) } @@ -2878,7 +2872,7 @@ impl<'a> Parser<'a> { /// Parse a prefix-unary-operator expr pub fn parse_prefix_expr(&mut self, - already_parsed_attrs: Option) + already_parsed_attrs: Option>) -> PResult<'a, P> { let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let lo = self.span.lo; @@ -2923,8 +2917,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) => { @@ -2944,7 +2937,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) + already_parsed_attrs: Option>) -> PResult<'a, P> { self.parse_assoc_expr_with(0, already_parsed_attrs.into()) } @@ -2997,13 +2990,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 @@ -3029,7 +3022,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 } @@ -3056,6 +3049,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 | @@ -3063,14 +3057,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, @@ -3084,9 +3077,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") @@ -3121,7 +3113,7 @@ impl<'a> Parser<'a> { /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr` fn parse_prefix_range_expr(&mut self, - already_parsed_attrs: Option) + already_parsed_attrs: Option>) -> PResult<'a, P> { debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot); let tok = self.token.clone(); @@ -3166,7 +3158,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> { + pub fn parse_if_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { if self.check_keyword(keywords::Let) { return self.parse_if_let_expr(attrs); } @@ -3184,7 +3176,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) -> PResult<'a, P> { let lo = self.last_span.lo; self.expect_keyword(keywords::Let)?; @@ -3205,7 +3197,7 @@ impl<'a> Parser<'a> { pub fn parse_lambda_expr(&mut self, lo: BytePos, capture_clause: CaptureBy, - attrs: ThinAttributes) + attrs: ThinVec) -> PResult<'a, P> { let decl = self.parse_fn_block_decl()?; @@ -3240,24 +3232,24 @@ impl<'a> Parser<'a> { // `else` token already eaten pub fn parse_else_expr(&mut self) -> PResult<'a, P> { 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, span_lo: BytePos, - attrs: ThinAttributes) -> PResult<'a, P> { + mut attrs: ThinVec) -> PResult<'a, P> { // Parse: `for in ` 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; @@ -3269,13 +3261,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, span_lo: BytePos, - attrs: ThinAttributes) -> PResult<'a, P> { + mut attrs: ThinVec) -> PResult<'a, P> { 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)); @@ -3284,13 +3276,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, span_lo: BytePos, - attrs: ThinAttributes) -> PResult<'a, P> { + mut attrs: ThinVec) -> PResult<'a, P> { 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)); } @@ -3298,15 +3290,15 @@ impl<'a> Parser<'a> { // parse `loop {...}`, `loop` token already eaten pub fn parse_loop_expr(&mut self, opt_ident: Option, span_lo: BytePos, - attrs: ThinAttributes) -> PResult<'a, P> { + mut attrs: ThinVec) -> PResult<'a, P> { 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> { + fn parse_match_expr(&mut self, mut attrs: ThinVec) -> PResult<'a, P> { let match_span = self.last_span; let lo = self.last_span.lo; let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, @@ -3318,8 +3310,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 = Vec::new(); while self.token != token::CloseDelim(token::Brace) { match self.parse_arm() { @@ -3392,7 +3384,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) + already_parsed_attrs: Option>) -> PResult<'a, P> { 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)?) }; 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() } @@ -3685,7 +3677,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); @@ -3785,7 +3778,7 @@ impl<'a> Parser<'a> { } /// Parse a local variable declaration - fn parse_local(&mut self, attrs: ThinAttributes) -> PResult<'a, P> { + fn parse_local(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.span.lo; let pat = self.parse_pat()?; @@ -3805,7 +3798,7 @@ impl<'a> Parser<'a> { } /// Parse a "let" stmt - fn parse_let(&mut self, attrs: ThinAttributes) -> PResult<'a, P> { + fn parse_let(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.span.lo; let local = self.parse_local(attrs)?; 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) { 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 stmt = StmtKind::Decl(decl, ast::DUMMY_NODE_ID); spanned(lo, hi, stmt) @@ -3980,7 +3973,7 @@ impl<'a> Parser<'a> { if id.name == keywords::Invalid.name() { 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) } else { // if it has a special ident, it's definitely an item @@ -4036,7 +4029,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()))?; let hi = e.span.hi; let stmt = StmtKind::Expr(e, ast::DUMMY_NODE_ID); spanned(lo, hi, stmt) @@ -4111,7 +4104,7 @@ impl<'a> Parser<'a> { _ => { let e = self.mk_mac_expr(span.lo, span.hi, mac.and_then(|m| m.node), - None); + 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 0c90e102f3425..620295fce889b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -14,7 +14,6 @@ use abi::{self, Abi}; use ast::{self, TokenTree, BlockCheckMode, PatKind}; use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Attribute; -use attr::ThinAttributesExt; use util::parser::AssocOp; use attr; use attr::{AttrMetaMethods, AttributeMethods}; @@ -1606,7 +1605,7 @@ impl<'a> State<'a> { } ast::StmtKind::Mac(ref mac, style, ref attrs) => { 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 @@ -1946,7 +1945,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 { @@ -2090,9 +2089,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 @@ -2281,7 +2278,7 @@ impl<'a> State<'a> { try!(self.maybe_print_comment(decl.span.lo)); match decl.node { 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.ibox(INDENT_UNIT)); try!(self.word_nbsp("let")); diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index ca6ed76d5499b..efeccc6acb6aa 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -604,10 +604,10 @@ fn mk_test_descs(cx: &TestCtxt) -> P { 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 0000000000000..546686b46b8db --- /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 or the MIT license +// , 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>` 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(Option>>); + +impl ThinVec { + pub fn new() -> Self { + ThinVec(None) + } +} + +impl From> for ThinVec { + fn from(vec: Vec) -> Self { + if vec.is_empty() { + ThinVec(None) + } else { + ThinVec(Some(Box::new(vec))) + } + } +} + +impl Into> for ThinVec { + fn into(self) -> Vec { + match self { + ThinVec(None) => Vec::new(), + ThinVec(Some(vec)) => *vec, + } + } +} + +impl ::std::ops::Deref for ThinVec { + type Target = [T]; + fn deref(&self) -> &[T] { + match *self { + ThinVec(None) => &[], + ThinVec(Some(ref vec)) => vec, + } + } +} + +impl Extend for ThinVec { + fn extend>(&mut self, iter: I) { + match *self { + ThinVec(Some(ref mut vec)) => vec.extend(iter), + ThinVec(None) => *self = iter.into_iter().collect::>().into(), + } + } +} diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 07a6317706b84..6588e3d60e1c2 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -25,7 +25,6 @@ use abi::Abi; use ast::*; -use attr::ThinAttributesExt; use codemap::{Span, Spanned}; #[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) { - for attr in local.attrs.as_attr_slice() { + for attr in local.attrs.iter() { visitor.visit_attribute(attr); } 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) => { visitor.visit_mac(mac); - for attr in attrs.as_attr_slice() { + for attr in attrs.iter() { 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) { - for attr in expression.attrs.as_attr_slice() { + for attr in expression.attrs.iter() { visitor.visit_attribute(attr); } match expression.node { diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 50d2b9d31fe01..bae21841b5ad1 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -260,6 +260,6 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) expn_id: expn_id, }), span: sp, - attrs: None, + attrs: ast::ThinVec::new(), })) } diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 09c23682cd73f..71c3251c1b18e 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -70,7 +70,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree]) id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Path(None, self.path()), span: self.span, - attrs: None, + attrs: ast::ThinVec::new(), })) } diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index d86eae820a884..3f695949b3949 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -149,7 +149,7 @@ fn stmt_let_undescore(cx: &mut ExtCtxt, init: Some(expr), id: ast::DUMMY_NODE_ID, span: sp, - attrs: None, + attrs: ast::ThinVec::new(), }); let decl = respan(sp, ast::DeclKind::Local(local)); respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)) diff --git a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs index ed971faf8c6a1..64747002a65b0 100644 --- a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs @@ -86,7 +86,7 @@ fn check_expr_attrs(es: &str, expected: &[&str]) { let actual = &e.attrs; str_compare(es, &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::>(), - actual.as_attr_slice(), + &actual, pprust::attribute_to_string); }