diff options
| author | bors <bors@rust-lang.org> | 2016-11-09 11:58:25 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-09 11:58:25 -0800 |
| commit | da2ce2276873242a101f205537e7ce297d68f8dd (patch) | |
| tree | b0de0fa6de932ca2ebeb973b7c92014903edb54e /src/libsyntax | |
| parent | bca365e688f0424fb99d38d477a9b7863bb070d3 (diff) | |
| parent | 60c74b76c4698d0223223e42853c5a89fd33fd09 (diff) | |
| download | rust-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.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/attr.rs | 26 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 45 |
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, |
