about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-11-09 11:58:25 -0800
committerGitHub <noreply@github.com>2016-11-09 11:58:25 -0800
commitda2ce2276873242a101f205537e7ce297d68f8dd (patch)
treeb0de0fa6de932ca2ebeb973b7c92014903edb54e /src/libsyntax
parentbca365e688f0424fb99d38d477a9b7863bb070d3 (diff)
parent60c74b76c4698d0223223e42853c5a89fd33fd09 (diff)
downloadrust-da2ce2276873242a101f205537e7ce297d68f8dd.tar.gz
rust-da2ce2276873242a101f205537e7ce297d68f8dd.zip
Auto merge of #37670 - eddyb:rollup, r=eddyb
Rollup of 15 pull requests

- Successful merges: #36868, #37134, #37229, #37250, #37370, #37428, #37432, #37472, #37524, #37614, #37622, #37627, #37636, #37644, #37654
- Failed merges: #37463, #37542, #37645
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/attr.rs26
-rw-r--r--src/libsyntax/feature_gate.rs45
3 files changed, 56 insertions, 23 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index f7581924eb1..9751ad6aa43 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -399,6 +399,14 @@ impl Generics {
     pub fn is_parameterized(&self) -> bool {
         self.is_lt_parameterized() || self.is_type_parameterized()
     }
+    pub fn span_for_name(&self, name: &str) -> Option<Span> {
+        for t in &self.ty_params {
+            if t.ident.name.as_str() == name {
+                return Some(t.span);
+            }
+        }
+        None
+    }
 }
 
 impl Default for Generics {
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 0335f210347..57a936bf9b0 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -32,7 +32,8 @@ use std::cell::{RefCell, Cell};
 use std::collections::HashSet;
 
 thread_local! {
-    static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new())
+    static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
+    static KNOWN_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
 }
 
 enum AttrError {
@@ -81,6 +82,29 @@ pub fn is_used(attr: &Attribute) -> bool {
     })
 }
 
+pub fn mark_known(attr: &Attribute) {
+    debug!("Marking {:?} as known.", attr);
+    let AttrId(id) = attr.node.id;
+    KNOWN_ATTRS.with(|slot| {
+        let idx = (id / 64) as usize;
+        let shift = id % 64;
+        if slot.borrow().len() <= idx {
+            slot.borrow_mut().resize(idx + 1, 0);
+        }
+        slot.borrow_mut()[idx] |= 1 << shift;
+    });
+}
+
+pub fn is_known(attr: &Attribute) -> bool {
+    let AttrId(id) = attr.node.id;
+    KNOWN_ATTRS.with(|slot| {
+        let idx = (id / 64) as usize;
+        let shift = id % 64;
+        slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0)
+            .unwrap_or(false)
+    })
+}
+
 impl NestedMetaItem {
     /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
     pub fn meta_item(&self) -> Option<&P<MetaItem>> {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index c5fae9f3236..a6493872338 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -271,7 +271,6 @@ declare_features! (
     // Allows `impl Trait` in function return types.
     (active, conservative_impl_trait, "1.12.0", Some(34511)),
 
-    // Allows tuple structs and variants in more contexts,
     // Permits numeric fields in struct expressions and patterns.
     (active, relaxed_adts, "1.12.0", Some(35626)),
 
@@ -422,11 +421,11 @@ macro_rules! cfg_fn {
 }
 
 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
-    KNOWN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
+    BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
 }
 
 // Attributes that have a special meaning to rustc or rustdoc
-pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
+pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
     // Normal attributes
 
     ("warn", Normal, Ungated),
@@ -801,12 +800,12 @@ impl<'a> Context<'a> {
     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
         let name = &*attr.name();
-        for &(n, ty, ref gateage) in KNOWN_ATTRIBUTES {
+        for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if n == name {
                 if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
                     gate_feature_fn!(self, has_feature, attr.span, name, desc);
                 }
-                debug!("check_attribute: {:?} is known, {:?}, {:?}", name, ty, gateage);
+                debug!("check_attribute: {:?} is builtin, {:?}, {:?}", name, ty, gateage);
                 return;
             }
         }
@@ -826,6 +825,8 @@ impl<'a> Context<'a> {
                            are reserved for internal compiler diagnostics");
         } else if name.starts_with("derive_") {
             gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
+        } else if attr::is_known(attr) {
+            debug!("check_attribute: {:?} is known", name);
         } else {
             // Only run the custom attribute lint during regular
             // feature gate checking. Macro gating runs
@@ -996,6 +997,10 @@ fn contains_novel_literal(item: &ast::MetaItem) -> bool {
     }
 }
 
+fn starts_with_digit(s: &str) -> bool {
+    s.as_bytes().first().cloned().map_or(false, |b| b >= b'0' && b <= b'9')
+}
+
 impl<'a> Visitor for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
         if !self.context.cm.span_allows_unstable(attr.span) {
@@ -1175,6 +1180,11 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
                         gate_feature_post!(&self, field_init_shorthand, field.span,
                                            "struct field shorthands are unstable");
                     }
+                    if starts_with_digit(&field.ident.node.name.as_str()) {
+                        gate_feature_post!(&self, relaxed_adts,
+                                          field.span,
+                                          "numeric fields in struct expressions are unstable");
+                    }
                 }
             }
             _ => {}
@@ -1201,10 +1211,14 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
                                   pattern.span,
                                   "box pattern syntax is experimental");
             }
-            PatKind::TupleStruct(_, ref fields, ddpos)
-                    if ddpos.is_none() && fields.is_empty() => {
-                gate_feature_post!(&self, relaxed_adts, pattern.span,
-                                   "empty tuple structs patterns are unstable");
+            PatKind::Struct(_, ref fields, _) => {
+                for field in fields {
+                    if starts_with_digit(&field.node.ident.name.as_str()) {
+                        gate_feature_post!(&self, relaxed_adts,
+                                          field.span,
+                                          "numeric fields in struct patterns are unstable");
+                    }
+                }
             }
             _ => {}
         }
@@ -1287,19 +1301,6 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_variant_data(&mut self, vdata: &ast::VariantData, _: ast::Ident,
-                          _: &ast::Generics, _: NodeId, span: Span) {
-        if vdata.fields().is_empty() {
-            if vdata.is_tuple() {
-                gate_feature_post!(&self, relaxed_adts, span,
-                                   "empty tuple structs and enum variants are unstable, \
-                                    use unit structs and enum variants instead");
-            }
-        }
-
-        visit::walk_struct_def(self, vdata)
-    }
-
     fn visit_vis(&mut self, vis: &ast::Visibility) {
         let span = match *vis {
             ast::Visibility::Crate(span) => span,