about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorcomex <comexk@gmail.com>2017-01-14 18:04:27 -0500
committercomex <comexk@gmail.com>2017-01-14 18:44:35 -0500
commit9cfb8b730a473814c2ae090c342abb95e53502db (patch)
treeac757a3acf31331c3ef7c9a0f3f063b1d85c9fd6 /src/libsyntax
parent743535a643ff9c7f5791a71f6b62c27617cdbb3e (diff)
parent93e70ecb7fbe05caa74dfb2bf3c29315edc2b3e6 (diff)
downloadrust-9cfb8b730a473814c2ae090c342abb95e53502db.tar.gz
rust-9cfb8b730a473814c2ae090c342abb95e53502db.zip
Merge branch 'master' into lint-attr-fix
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/attr.rs32
-rw-r--r--src/libsyntax/config.rs69
-rw-r--r--src/libsyntax/ext/build.rs8
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax/feature_gate.rs15
-rw-r--r--src/libsyntax/fold.rs16
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/parser.rs13
-rw-r--r--src/libsyntax/visit.rs2
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)
             }