diff options
| author | comex <comexk@gmail.com> | 2017-01-14 18:04:27 -0500 |
|---|---|---|
| committer | comex <comexk@gmail.com> | 2017-01-14 18:44:35 -0500 |
| commit | 9cfb8b730a473814c2ae090c342abb95e53502db (patch) | |
| tree | ac757a3acf31331c3ef7c9a0f3f063b1d85c9fd6 /src/libsyntax | |
| parent | 743535a643ff9c7f5791a71f6b62c27617cdbb3e (diff) | |
| parent | 93e70ecb7fbe05caa74dfb2bf3c29315edc2b3e6 (diff) | |
| download | rust-9cfb8b730a473814c2ae090c342abb95e53502db.tar.gz rust-9cfb8b730a473814c2ae090c342abb95e53502db.zip | |
Merge branch 'master' into lint-attr-fix
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/attr.rs | 32 | ||||
| -rw-r--r-- | src/libsyntax/config.rs | 69 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/lib.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
10 files changed, 124 insertions, 37 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index da4b787160f..709de49fbaa 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -538,6 +538,7 @@ pub struct FieldPat { /// The pattern the field is destructured to pub pat: P<Pat>, pub is_shorthand: bool, + pub attrs: ThinVec<Attribute>, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -815,6 +816,7 @@ pub struct Field { pub expr: P<Expr>, pub span: Span, pub is_shorthand: bool, + pub attrs: ThinVec<Attribute>, } pub type SpannedIdent = Spanned<Ident>; diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index ab8a49b41f2..099ca8f02d2 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -18,7 +18,7 @@ use ast; use ast::{AttrId, Attribute, Name}; use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use ast::{Lit, Expr, Item, Local, Stmt, StmtKind}; -use codemap::{spanned, dummy_spanned, mk_sp}; +use codemap::{Spanned, spanned, dummy_spanned, mk_sp}; use syntax_pos::{Span, BytePos, DUMMY_SP}; use errors::Handler; use feature_gate::{Features, GatedCfg}; @@ -959,6 +959,13 @@ pub trait HasAttrs: Sized { fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self; } +impl<T: HasAttrs> HasAttrs for Spanned<T> { + fn attrs(&self) -> &[ast::Attribute] { self.node.attrs() } + fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self { + Spanned { node: self.node.map_attrs(f), span: self.span } + } +} + impl HasAttrs for Vec<Attribute> { fn attrs(&self) -> &[Attribute] { &self @@ -1012,26 +1019,31 @@ impl HasAttrs for StmtKind { } } -macro_rules! derive_has_attrs_from_field { - ($($ty:path),*) => { derive_has_attrs_from_field!($($ty: .attrs),*); }; - ($($ty:path : $(.$field:ident)*),*) => { $( +impl HasAttrs for Stmt { + fn attrs(&self) -> &[ast::Attribute] { self.node.attrs() } + fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self { + Stmt { id: self.id, node: self.node.map_attrs(f), span: self.span } + } +} + +macro_rules! derive_has_attrs { + ($($ty:path),*) => { $( impl HasAttrs for $ty { fn attrs(&self) -> &[Attribute] { - self $(.$field)* .attrs() + &self.attrs } fn map_attrs<F>(mut self, f: F) -> Self where F: FnOnce(Vec<Attribute>) -> Vec<Attribute>, { - self $(.$field)* = self $(.$field)* .map_attrs(f); + self.attrs = self.attrs.map_attrs(f); self } } )* } } -derive_has_attrs_from_field! { - Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm +derive_has_attrs! { + Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, + ast::Field, ast::FieldPat, ast::Variant_ } - -derive_has_attrs_from_field! { Stmt: .node, ast::Variant: .node.attrs } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 89eea3f6f8b..ea12a31770f 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -221,11 +221,21 @@ impl<'a> StripUnconfigured<'a> { } pub fn configure_expr_kind(&mut self, expr_kind: ast::ExprKind) -> ast::ExprKind { - if let ast::ExprKind::Match(m, arms) = expr_kind { - let arms = arms.into_iter().filter_map(|a| self.configure(a)).collect(); - ast::ExprKind::Match(m, arms) - } else { - expr_kind + match expr_kind { + ast::ExprKind::Match(m, arms) => { + let arms = arms.into_iter().filter_map(|a| self.configure(a)).collect(); + ast::ExprKind::Match(m, arms) + } + ast::ExprKind::Struct(path, fields, base) => { + let fields = fields.into_iter() + .filter_map(|field| { + self.visit_struct_field_attrs(field.attrs()); + self.configure(field) + }) + .collect(); + ast::ExprKind::Struct(path, fields, base) + } + _ => expr_kind, } } @@ -250,6 +260,51 @@ impl<'a> StripUnconfigured<'a> { pub fn configure_stmt(&mut self, stmt: ast::Stmt) -> Option<ast::Stmt> { self.configure(stmt) } + + pub fn configure_struct_expr_field(&mut self, field: ast::Field) -> Option<ast::Field> { + if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) { + if !field.attrs.is_empty() { + let mut err = feature_err(&self.sess, + "struct_field_attributes", + field.span, + GateIssue::Language, + "attributes on struct literal fields are unstable"); + err.emit(); + } + } + + self.configure(field) + } + + pub fn configure_pat(&mut self, pattern: P<ast::Pat>) -> P<ast::Pat> { + pattern.map(|mut pattern| { + if let ast::PatKind::Struct(path, fields, etc) = pattern.node { + let fields = fields.into_iter() + .filter_map(|field| { + self.visit_struct_field_attrs(field.attrs()); + self.configure(field) + }) + .collect(); + pattern.node = ast::PatKind::Struct(path, fields, etc); + } + pattern + }) + } + + fn visit_struct_field_attrs(&mut self, attrs: &[ast::Attribute]) { + // flag the offending attributes + for attr in attrs.iter() { + if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) { + let mut err = feature_err( + &self.sess, + "struct_field_attributes", + attr.span, + GateIssue::Language, + "attributes on struct pattern or literal fields are unstable"); + err.emit(); + } + } + } } impl<'a> fold::Folder for StripUnconfigured<'a> { @@ -299,6 +354,10 @@ impl<'a> fold::Folder for StripUnconfigured<'a> { // Interpolated AST will get configured once the surrounding tokens are parsed. mac } + + fn fold_pat(&mut self, pattern: P<ast::Pat>) -> P<ast::Pat> { + fold::noop_fold_pat(self.configure_pat(pattern), self) + } } fn is_cfg(attr: &ast::Attribute) -> bool { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 28f0c297303..688df96ffa3 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -699,7 +699,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(b.span, ast::ExprKind::Block(b)) } fn field_imm(&self, span: Span, name: Ident, e: P<ast::Expr>) -> ast::Field { - ast::Field { ident: respan(span, name), expr: e, span: span, is_shorthand: false } + ast::Field { + ident: respan(span, name), + expr: e, + span: span, + is_shorthand: false, + attrs: ast::ThinVec::new(), + } } fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec<ast::Field>) -> P<ast::Expr> { self.expr(span, ast::ExprKind::Struct(path, fields, None)) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5d62175fbf2..201e8d69494 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -679,6 +679,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { } fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> { + let pat = self.cfg.configure_pat(pat); match pat.node { PatKind::Mac(_) => {} _ => return noop_fold_pat(pat, self), @@ -926,7 +927,6 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_allow_internal_unstable = allow_internal_unstable, fn enable_custom_derive = custom_derive, fn enable_pushpop_unsafe = pushpop_unsafe, - fn enable_proc_macro = proc_macro, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e7df454cf6a..90cca3129dc 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -279,9 +279,6 @@ declare_features! ( // instead of just the platforms on which it is the C ABI (active, abi_sysv64, "1.13.0", Some(36167)), - // Macros 1.1 - (active, proc_macro, "1.13.0", Some(35900)), - // Allows untagged unions `union U { ... }` (active, untagged_unions, "1.13.0", Some(32836)), @@ -327,6 +324,9 @@ declare_features! ( // The `unadjusted` ABI. Perma unstable. (active, abi_unadjusted, "1.16.0", None), + + // Allows attributes on struct literal fields. + (active, struct_field_attributes, "1.16.0", Some(38814)), ); declare_features! ( @@ -377,6 +377,8 @@ declare_features! ( // Allows `..` in tuple (struct) patterns (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)), (accepted, item_like_imports, "1.14.0", Some(35120)), + // Macros 1.1 + (accepted, proc_macro, "1.15.0", Some(35900)), ); // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -650,11 +652,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG is an experimental feature", cfg_fn!(fundamental))), - ("proc_macro_derive", Normal, Gated(Stability::Unstable, - "proc_macro", - "the `#[proc_macro_derive]` attribute \ - is an experimental feature", - cfg_fn!(proc_macro))), + ("proc_macro_derive", Normal, Ungated), ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", @@ -760,7 +758,6 @@ const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)), ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)), ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)), - ("proc_macro", "proc_macro", cfg_fn!(proc_macro)), ]; #[derive(Debug, Eq, PartialEq)] diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 9797e0003fc..10ca9da2112 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -542,19 +542,19 @@ pub fn noop_fold_arg<T: Folder>(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg { pub fn noop_fold_tt<T: Folder>(tt: &TokenTree, fld: &mut T) -> TokenTree { match *tt { TokenTree::Token(span, ref tok) => - TokenTree::Token(span, fld.fold_token(tok.clone())), + TokenTree::Token(fld.new_span(span), fld.fold_token(tok.clone())), TokenTree::Delimited(span, ref delimed) => { - TokenTree::Delimited(span, Rc::new( + TokenTree::Delimited(fld.new_span(span), Rc::new( Delimited { delim: delimed.delim, - open_span: delimed.open_span, + open_span: fld.new_span(delimed.open_span), tts: fld.fold_tts(&delimed.tts), - close_span: delimed.close_span, + close_span: fld.new_span(delimed.close_span), } )) }, TokenTree::Sequence(span, ref seq) => - TokenTree::Sequence(span, + TokenTree::Sequence(fld.new_span(span), Rc::new(SequenceRepetition { tts: fld.fold_tts(&seq.tts), separator: seq.separator.clone().map(|tok| fld.fold_token(tok)), @@ -647,7 +647,7 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> { inputs: inputs.move_map(|x| fld.fold_arg(x)), output: match output { FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(fld.fold_ty(ty)), - FunctionRetTy::Default(span) => FunctionRetTy::Default(span), + FunctionRetTy::Default(span) => FunctionRetTy::Default(fld.new_span(span)), }, variadic: variadic }) @@ -674,7 +674,7 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam { ident: fld.fold_ident(ident), bounds: fld.fold_bounds(bounds), default: default.map(|x| fld.fold_ty(x)), - span: span + span: fld.new_span(span), } } @@ -830,6 +830,7 @@ pub fn noop_fold_field<T: Folder>(f: Field, folder: &mut T) -> Field { expr: folder.fold_expr(f.expr), span: folder.new_span(f.span), is_shorthand: f.is_shorthand, + attrs: fold_thin_attrs(f.attrs, folder), } } @@ -1089,6 +1090,7 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> { ident: folder.fold_ident(f.node.ident), pat: folder.fold_pat(f.node.pat), is_shorthand: f.node.is_shorthand, + attrs: fold_attrs(f.node.attrs.into(), folder).into() }} }); PatKind::Struct(pth, fs, etc) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 5d6808284f6..00bf7445077 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -22,7 +22,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(associated_consts)] #![feature(const_fn)] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2bb38433a26..167fa78d7e0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1946,6 +1946,7 @@ impl<'a> Parser<'a> { /// Parse ident (COLON expr)? pub fn parse_field(&mut self) -> PResult<'a, Field> { + let attrs = self.parse_outer_attributes()?; let lo = self.span.lo; let hi; @@ -1968,6 +1969,7 @@ impl<'a> Parser<'a> { span: mk_sp(lo, expr.span.hi), expr: expr, is_shorthand: is_shorthand, + attrs: attrs.into(), }) } @@ -3436,6 +3438,7 @@ impl<'a> Parser<'a> { if self.check(&token::CloseDelim(token::Brace)) { break } } + let attrs = self.parse_outer_attributes()?; let lo = self.span.lo; let hi; @@ -3493,9 +3496,13 @@ impl<'a> Parser<'a> { }; fields.push(codemap::Spanned { span: mk_sp(lo, hi), - node: ast::FieldPat { ident: fieldname, - pat: subpat, - is_shorthand: is_shorthand }}); + node: ast::FieldPat { + ident: fieldname, + pat: subpat, + is_shorthand: is_shorthand, + attrs: attrs.into(), + } + }); } return Ok((fields, etc)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index ad29cb50a84..04100b3af00 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -427,6 +427,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { PatKind::Struct(ref path, ref fields, _) => { visitor.visit_path(path, pattern.id); for field in fields { + walk_list!(visitor, visit_attribute, field.node.attrs.iter()); visitor.visit_ident(field.span, field.node.ident); visitor.visit_pat(&field.node.pat) } @@ -659,6 +660,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Struct(ref path, ref fields, ref optional_base) => { visitor.visit_path(path, expression.id); for field in fields { + walk_list!(visitor, visit_attribute, field.attrs.iter()); visitor.visit_ident(field.ident.span, field.ident.node); visitor.visit_expr(&field.expr) } |
