From 10855a36b53d33aa2e4f8b98107ee54a0cca5e9c Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 3 Apr 2019 02:43:49 +0200 Subject: Use a proc macro to declare preallocated symbols --- src/libsyntax/ast.rs | 6 ++++++ src/libsyntax/attr/mod.rs | 21 +++++++++++++++++++++ src/libsyntax/feature_gate.rs | 28 ++++++++++++++-------------- 3 files changed, 41 insertions(+), 14 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index cf909e30e32..c015e9b06ac 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -68,6 +68,12 @@ pub struct Path { pub segments: Vec, } +impl PartialEq for Path { + fn eq(&self, symbol: &Symbol) -> bool { + self.segments.len() == 1 && self.segments[0].ident.name.interned() == *symbol + } +} + impl<'a> PartialEq<&'a str> for Path { fn eq(&self, string: &&'a str) -> bool { self.segments.len() == 1 && self.segments[0].ident.name == *string diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index c0bd5c79b1d..f34bbc9f35d 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -85,6 +85,11 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } + /// Returns `true` if this list item is a MetaItem with a name of `name`. + pub fn check_name_symbol(&self, name: Symbol) -> bool { + self.meta_item().map_or(false, |meta_item| meta_item.check_name_symbol(name)) + } + /// For a single-segment meta-item returns its name, otherwise returns `None`. pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) @@ -159,6 +164,18 @@ impl Attribute { matches } + /// Returns `true` if the attribute's path matches the argument. If it matches, then the + /// attribute is marked as used. + /// + /// To check the attribute name without marking it used, use the `path` field directly. + pub fn check_name_symbol(&self, name: Symbol) -> bool { + let matches = self.path == name; + if matches { + mark_used(self); + } + matches + } + /// For a single-segment attribute returns its name, otherwise returns `None`. pub fn ident(&self) -> Option { if self.path.segments.len() == 1 { @@ -248,6 +265,10 @@ impl MetaItem { self.path == name } + pub fn check_name_symbol(&self, name: Symbol) -> bool { + self.path == name + } + pub fn is_value_str(&self) -> bool { self.value_str().is_some() } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f77593ed02a..b3e5d808a47 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -28,7 +28,7 @@ use crate::tokenstream::TokenTree; use errors::{DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::{Span, DUMMY_SP, symbols}; use log::debug; use std::env; @@ -1366,7 +1366,7 @@ impl<'a> Context<'a> { } } else if n == "doc" { if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name("include")) { + if content.iter().any(|c| c.check_name_symbol(symbols::include)) { gate_feature!(self, external_doc, attr.span, "#[doc(include = \"...\")] is experimental" ); @@ -1667,25 +1667,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // check for gated attributes self.context.check_attribute(attr, false); - if attr.check_name("doc") { + if attr.check_name_symbol(symbols::doc) { if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name("cfg") { + if content.len() == 1 && content[0].check_name_symbol(symbols::cfg) { gate_feature_post!(&self, doc_cfg, attr.span, "#[doc(cfg(...))] is experimental" ); - } else if content.iter().any(|c| c.check_name("masked")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::masked)) { gate_feature_post!(&self, doc_masked, attr.span, "#[doc(masked)] is experimental" ); - } else if content.iter().any(|c| c.check_name("spotlight")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::spotlight)) { gate_feature_post!(&self, doc_spotlight, attr.span, "#[doc(spotlight)] is experimental" ); - } else if content.iter().any(|c| c.check_name("alias")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::alias)) { gate_feature_post!(&self, doc_alias, attr.span, "#[doc(alias = \"...\")] is experimental" ); - } else if content.iter().any(|c| c.check_name("keyword")) { + } else if content.iter().any(|c| c.check_name_symbol(symbols::keyword)) { gate_feature_post!(&self, doc_keyword, attr.span, "#[doc(keyword = \"...\")] is experimental" ); @@ -1693,7 +1693,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - match BUILTIN_ATTRIBUTES.iter().find(|(name, ..)| attr.path == name) { + match BUILTIN_ATTRIBUTES.iter().find(|(name, ..)| attr.path == *name) { Some(&(name, _, template, _)) => self.check_builtin_attribute(attr, name, template), None => if let Some(TokenTree::Token(_, token::Eq)) = attr.tokens.trees().next() { // All key-value attributes are restricted to meta-item syntax. @@ -1748,7 +1748,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Struct(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name("simd") { + if item.check_name_symbol(symbols::simd) { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } @@ -1759,7 +1759,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Enum(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name("align") { + if item.check_name_symbol(symbols::align) { gate_feature_post!(&self, repr_align_enum, attr.span, "`#[repr(align(x))]` on enums is experimental"); } @@ -2083,7 +2083,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], // Process the edition umbrella feature-gates first, to ensure // `edition_enabled_features` is completed before it's queried. for attr in krate_attrs { - if !attr.check_name("feature") { + if !attr.check_name_symbol(symbols::feature) { continue } @@ -2128,7 +2128,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } for attr in krate_attrs { - if !attr.check_name("feature") { + if !attr.check_name_symbol(symbols::feature) { continue } @@ -2258,7 +2258,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, }; if !allow_features { for attr in &krate.attrs { - if attr.check_name("feature") { + if attr.check_name_symbol(symbols::feature) { let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); span_err!(span_handler, attr.span, E0554, "#![feature] may not be used on the {} release channel", -- cgit 1.4.1-3-g733a5 From 61a7a60d45fd20bee343a37693969a32e63cb905 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Fri, 5 Apr 2019 03:05:30 +0200 Subject: Make check_name generic --- src/librustc/middle/lib_features.rs | 6 ++--- src/librustc_incremental/persist/dirty_clean.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/libsyntax/attr/mod.rs | 36 +++++++++---------------- src/libsyntax/feature_gate.rs | 24 ++++++++--------- src/libsyntax_ext/proc_macro_decls.rs | 2 +- src/libsyntax_pos/symbol.rs | 3 ++- 7 files changed, 32 insertions(+), 43 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index ee8dd9e58b5..e79ef8bfc6f 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -8,7 +8,7 @@ use crate::ty::TyCtxt; use crate::hir::intravisit::{self, NestedVisitorMap, Visitor}; use syntax::symbol::Symbol; use syntax::ast::{Attribute, MetaItem, MetaItemKind}; -use syntax_pos::Span; +use syntax_pos::{Span, symbols}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_macros::HashStable; use errors::DiagnosticId; @@ -51,12 +51,12 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { } fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { - let stab_attrs = vec!["stable", "unstable", "rustc_const_unstable"]; + let stab_attrs = [symbols::stable, symbols::unstable, symbols::rustc_const_unstable]; // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, // `#[rustc_const_unstable (..)]`). if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| { - attr.check_name(stab_attr) + attr.check_name(**stab_attr) }) { let meta_item = attr.meta(); if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item { diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 5c4fd9dba7a..6f5b411946c 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -599,7 +599,7 @@ impl<'a, 'tcx> FindAllAttrs<'a, 'tcx> { fn is_active_attr(&mut self, attr: &Attribute) -> bool { for attr_name in &self.attr_names { - if attr.check_name(attr_name) && check_config(self.tcx, attr) { + if attr.check_name(*attr_name) && check_config(self.tcx, attr) { return true; } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d41d97f58bc..2aee21abb58 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { let plugin_attributes = cx.sess().plugin_attributes.borrow_mut(); for &(ref name, ty) in plugin_attributes.iter() { - if ty == AttributeType::Whitelisted && attr.check_name(&name) { + if ty == AttributeType::Whitelisted && attr.check_name(&**name) { debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty); break; } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index f34bbc9f35d..e00f91e3952 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -81,15 +81,13 @@ impl NestedMetaItem { } /// Returns `true` if this list item is a MetaItem with a name of `name`. - pub fn check_name(&self, name: &str) -> bool { + pub fn check_name(&self, name: T) -> bool + where + Path: PartialEq, + { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } - /// Returns `true` if this list item is a MetaItem with a name of `name`. - pub fn check_name_symbol(&self, name: Symbol) -> bool { - self.meta_item().map_or(false, |meta_item| meta_item.check_name_symbol(name)) - } - /// For a single-segment meta-item returns its name, otherwise returns `None`. pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) @@ -156,19 +154,10 @@ impl Attribute { /// attribute is marked as used. /// /// To check the attribute name without marking it used, use the `path` field directly. - pub fn check_name(&self, name: &str) -> bool { - let matches = self.path == name; - if matches { - mark_used(self); - } - matches - } - - /// Returns `true` if the attribute's path matches the argument. If it matches, then the - /// attribute is marked as used. - /// - /// To check the attribute name without marking it used, use the `path` field directly. - pub fn check_name_symbol(&self, name: Symbol) -> bool { + pub fn check_name(&self, name: T) -> bool + where + Path: PartialEq, + { let matches = self.path == name; if matches { mark_used(self); @@ -261,11 +250,10 @@ impl MetaItem { } } - pub fn check_name(&self, name: &str) -> bool { - self.path == name - } - - pub fn check_name_symbol(&self, name: Symbol) -> bool { + pub fn check_name(&self, name: T) -> bool + where + Path: PartialEq, + { self.path == name } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b3e5d808a47..ba4380416fb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1366,7 +1366,7 @@ impl<'a> Context<'a> { } } else if n == "doc" { if let Some(content) = attr.meta_item_list() { - if content.iter().any(|c| c.check_name_symbol(symbols::include)) { + if content.iter().any(|c| c.check_name(symbols::include)) { gate_feature!(self, external_doc, attr.span, "#[doc(include = \"...\")] is experimental" ); @@ -1667,25 +1667,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // check for gated attributes self.context.check_attribute(attr, false); - if attr.check_name_symbol(symbols::doc) { + if attr.check_name(symbols::doc) { if let Some(content) = attr.meta_item_list() { - if content.len() == 1 && content[0].check_name_symbol(symbols::cfg) { + if content.len() == 1 && content[0].check_name(symbols::cfg) { gate_feature_post!(&self, doc_cfg, attr.span, "#[doc(cfg(...))] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::masked)) { + } else if content.iter().any(|c| c.check_name(symbols::masked)) { gate_feature_post!(&self, doc_masked, attr.span, "#[doc(masked)] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::spotlight)) { + } else if content.iter().any(|c| c.check_name(symbols::spotlight)) { gate_feature_post!(&self, doc_spotlight, attr.span, "#[doc(spotlight)] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::alias)) { + } else if content.iter().any(|c| c.check_name(symbols::alias)) { gate_feature_post!(&self, doc_alias, attr.span, "#[doc(alias = \"...\")] is experimental" ); - } else if content.iter().any(|c| c.check_name_symbol(symbols::keyword)) { + } else if content.iter().any(|c| c.check_name(symbols::keyword)) { gate_feature_post!(&self, doc_keyword, attr.span, "#[doc(keyword = \"...\")] is experimental" ); @@ -1748,7 +1748,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Struct(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name_symbol(symbols::simd) { + if item.check_name(symbols::simd) { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } @@ -1759,7 +1759,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Enum(..) => { for attr in attr::filter_by_name(&i.attrs[..], "repr") { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { - if item.check_name_symbol(symbols::align) { + if item.check_name(symbols::align) { gate_feature_post!(&self, repr_align_enum, attr.span, "`#[repr(align(x))]` on enums is experimental"); } @@ -2083,7 +2083,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], // Process the edition umbrella feature-gates first, to ensure // `edition_enabled_features` is completed before it's queried. for attr in krate_attrs { - if !attr.check_name_symbol(symbols::feature) { + if !attr.check_name(symbols::feature) { continue } @@ -2128,7 +2128,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } for attr in krate_attrs { - if !attr.check_name_symbol(symbols::feature) { + if !attr.check_name(symbols::feature) { continue } @@ -2258,7 +2258,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, }; if !allow_features { for attr in &krate.attrs { - if attr.check_name_symbol(symbols::feature) { + if attr.check_name(symbols::feature) { let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); span_err!(span_handler, attr.span, E0554, "#![feature] may not be used on the {} release channel", diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 22fee902aea..f0390ba3d40 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -87,7 +87,7 @@ pub fn modify(sess: &ParseSess, } pub fn is_proc_macro_attr(attr: &ast::Attribute) -> bool { - PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(kind)) + PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(*kind)) } impl<'a> CollectProcMacros<'a> { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 8c195fb45ef..83cb6f4e86b 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -100,7 +100,8 @@ symbols! { // Other symbols that can be referred to with syntax_pos::symbols::* Other { - doc, cfg, masked, spotlight, alias, keyword, feature, include, simd, align, + doc, cfg, masked, spotlight, alias, keyword, feature, include, simd, align, stable, + unstable, rustc_const_unstable, } } -- cgit 1.4.1-3-g733a5 From afeda72dad761325ea759fd2008730e24a165b9c Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Tue, 9 Apr 2019 09:18:49 +0200 Subject: Ensure the symbols are pure strings --- src/libsyntax/ast.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c015e9b06ac..0668730b3ef 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -70,7 +70,13 @@ pub struct Path { impl PartialEq for Path { fn eq(&self, symbol: &Symbol) -> bool { - self.segments.len() == 1 && self.segments[0].ident.name.interned() == *symbol + self.segments.len() == 1 && { + let name = self.segments[0].ident.name; + // Make sure these symbols are pure strings + debug_assert!(!symbol.is_gensymed()); + debug_assert!(!name.is_gensymed()); + name == *symbol + } } } -- cgit 1.4.1-3-g733a5