]> git.proxmox.com Git - rustc.git/blobdiff - src/libsyntax/attr.rs
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / libsyntax / attr.rs
index eeb832d48b0d89675574a2eab825bfd9debeafa4..e828d8ae24874fd4773e2fdbf054dc1c3dd445b7 100644 (file)
@@ -16,10 +16,13 @@ pub use self::IntType::*;
 
 use ast;
 use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, MetaList};
+use ast::{Stmt, StmtDecl, StmtExpr, StmtMac, StmtSemi, DeclItem, DeclLocal};
+use ast::{Expr, Item, Local, Decl};
 use codemap::{Span, Spanned, spanned, dummy_spanned};
 use codemap::BytePos;
+use config::CfgDiag;
 use diagnostic::SpanHandler;
-use feature_gate::GatedCfg;
+use feature_gate::{GatedCfg, GatedCfgAttr};
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
 use parse::token::{InternedString, intern_and_get_ident};
 use parse::token;
@@ -67,7 +70,7 @@ pub trait AttrMetaMethods {
     /// containing a string, otherwise None.
     fn value_str(&self) -> Option<InternedString>;
     /// Gets a list of inner meta items from a list MetaItem type.
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]>;
+    fn meta_item_list(&self) -> Option<&[P<MetaItem>]>;
 
     fn span(&self) -> Span;
 }
@@ -84,7 +87,7 @@ impl AttrMetaMethods for Attribute {
     fn value_str(&self) -> Option<InternedString> {
         self.meta().value_str()
     }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
+    fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
         self.node.value.meta_item_list()
     }
     fn span(&self) -> Span { self.meta().span }
@@ -111,7 +114,7 @@ impl AttrMetaMethods for MetaItem {
         }
     }
 
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
+    fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
         match self.node {
             MetaList(_, ref l) => Some(&l[..]),
             _ => None
@@ -124,7 +127,7 @@ impl AttrMetaMethods for MetaItem {
 impl AttrMetaMethods for P<MetaItem> {
     fn name(&self) -> InternedString { (**self).name() }
     fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
+    fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
         (**self).meta_item_list()
     }
     fn span(&self) -> Span { (**self).span() }
@@ -132,14 +135,14 @@ impl AttrMetaMethods for P<MetaItem> {
 
 
 pub trait AttributeMethods {
-    fn meta<'a>(&'a self) -> &'a MetaItem;
+    fn meta(&self) -> &MetaItem;
     fn with_desugared_doc<T, F>(&self, f: F) -> T where
         F: FnOnce(&Attribute) -> T;
 }
 
 impl AttributeMethods for Attribute {
     /// Extract the MetaItem from inside this Attribute.
-    fn meta<'a>(&'a self) -> &'a MetaItem {
+    fn meta(&self) -> &MetaItem {
         &*self.node.value
     }
 
@@ -356,32 +359,41 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool {
 }
 
 /// Tests if a cfg-pattern matches the cfg set
-pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::MetaItem,
-                   feature_gated_cfgs: &mut Vec<GatedCfg>) -> bool {
+pub fn cfg_matches<T: CfgDiag>(cfgs: &[P<MetaItem>],
+                           cfg: &ast::MetaItem,
+                           diag: &mut T) -> bool {
     match cfg.node {
         ast::MetaList(ref pred, ref mis) if &pred[..] == "any" =>
-            mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi, feature_gated_cfgs)),
+            mis.iter().any(|mi| cfg_matches(cfgs, &**mi, diag)),
         ast::MetaList(ref pred, ref mis) if &pred[..] == "all" =>
-            mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi, feature_gated_cfgs)),
+            mis.iter().all(|mi| cfg_matches(cfgs, &**mi, diag)),
         ast::MetaList(ref pred, ref mis) if &pred[..] == "not" => {
             if mis.len() != 1 {
-                diagnostic.span_err(cfg.span, "expected 1 cfg-pattern");
+                diag.emit_error(|diagnostic| {
+                    diagnostic.span_err(cfg.span, "expected 1 cfg-pattern");
+                });
                 return false;
             }
-            !cfg_matches(diagnostic, cfgs, &*mis[0], feature_gated_cfgs)
+            !cfg_matches(cfgs, &*mis[0], diag)
         }
         ast::MetaList(ref pred, _) => {
-            diagnostic.span_err(cfg.span, &format!("invalid predicate `{}`", pred));
+            diag.emit_error(|diagnostic| {
+                diagnostic.span_err(cfg.span,
+                    &format!("invalid predicate `{}`", pred));
+            });
             false
         },
         ast::MetaWord(_) | ast::MetaNameValue(..) => {
-            feature_gated_cfgs.extend(GatedCfg::gate(cfg));
+            diag.flag_gated(|feature_gated_cfgs| {
+                feature_gated_cfgs.extend(
+                    GatedCfg::gate(cfg).map(GatedCfgAttr::GatedCfg));
+            });
             contains(cfgs, cfg)
         }
     }
 }
 
-/// Represents the #[stable], #[unstable] and #[deprecated] attributes.
+/// Represents the #[stable], #[unstable] and #[rustc_deprecated] attributes.
 #[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
@@ -420,7 +432,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
     'outer: for attr in attrs_iter {
         let tag = attr.name();
         let tag = &*tag;
-        if tag != "deprecated" && tag != "unstable" && tag != "stable" {
+        if tag != "rustc_deprecated" && tag != "unstable" && tag != "stable" {
             continue // not a stability level
         }
 
@@ -443,9 +455,9 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
             };
 
             match tag {
-                "deprecated" => {
+                "rustc_deprecated" => {
                     if depr.is_some() {
-                        diagnostic.span_err(item_sp, "multiple deprecated attributes");
+                        diagnostic.span_err(item_sp, "multiple rustc_deprecated attributes");
                         break
                     }
 
@@ -586,7 +598,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
             }
             stab.depr = Some(depr);
         } else {
-            diagnostic.span_err(item_sp, "deprecated attribute must be paired with \
+            diagnostic.span_err(item_sp, "rustc_deprecated attribute must be paired with \
                                           either stable or unstable attribute");
         }
     }
@@ -720,3 +732,157 @@ 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))
+        }
+    }
+}
+
+/// A cheap way to add Attributes to an AST node.
+pub trait WithAttrs {
+    // FIXME: Could be extended to anything IntoIter<Item=Attribute>
+    fn with_attrs(self, attrs: ThinAttributes) -> Self;
+}
+
+impl WithAttrs for P<Expr> {
+    fn with_attrs(self, attrs: ThinAttributes) -> Self {
+        self.map(|mut e| {
+            e.attrs.update(|a| a.append(attrs));
+            e
+        })
+    }
+}
+
+impl WithAttrs for P<Item> {
+    fn with_attrs(self, attrs: ThinAttributes) -> Self {
+        self.map(|Item { ident, attrs: mut ats, id, node, vis, span }| {
+            ats.extend(attrs.into_attr_vec());
+            Item {
+                ident: ident,
+                attrs: ats,
+                id: id,
+                node: node,
+                vis: vis,
+                span: span,
+            }
+        })
+    }
+}
+
+impl WithAttrs for P<Local> {
+    fn with_attrs(self, attrs: ThinAttributes) -> Self {
+        self.map(|Local { pat, ty, init, id, span, attrs: mut ats }| {
+            ats.update(|a| a.append(attrs));
+            Local {
+                pat: pat,
+                ty: ty,
+                init: init,
+                id: id,
+                span: span,
+                attrs: ats,
+            }
+        })
+    }
+}
+
+impl WithAttrs for P<Decl> {
+    fn with_attrs(self, attrs: ThinAttributes) -> Self {
+        self.map(|Spanned { span, node }| {
+            Spanned {
+                span: span,
+                node: match node {
+                    DeclLocal(local) => DeclLocal(local.with_attrs(attrs)),
+                    DeclItem(item) => DeclItem(item.with_attrs(attrs)),
+                }
+            }
+        })
+    }
+}
+
+impl WithAttrs for P<Stmt> {
+    fn with_attrs(self, attrs: ThinAttributes) -> Self {
+        self.map(|Spanned { span, node }| {
+            Spanned {
+                span: span,
+                node: match node {
+                    StmtDecl(decl, id) => StmtDecl(decl.with_attrs(attrs), id),
+                    StmtExpr(expr, id) => StmtExpr(expr.with_attrs(attrs), id),
+                    StmtSemi(expr, id) => StmtSemi(expr.with_attrs(attrs), id),
+                    StmtMac(mac, style, mut ats) => {
+                        ats.update(|a| a.append(attrs));
+                        StmtMac(mac, style, ats)
+                    }
+                },
+            }
+        })
+    }
+}