about summary refs log tree commit diff
path: root/src/libsyntax/attr
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-12-01 00:39:18 +0000
committerbors <bors@rust-lang.org>2019-12-01 00:39:18 +0000
commit135ccbaca86ed4b9c0efaf0cd31442eae57ffad7 (patch)
treef5d91a593d425871fff9e1b68ac2e9f982d6c8e1 /src/libsyntax/attr
parentd8bdb3fdcbd88eb16e1a6669236122c41ed2aed3 (diff)
parentb772b5b19d769e7062b032e6e73f6466b26d78bd (diff)
downloadrust-135ccbaca86ed4b9c0efaf0cd31442eae57ffad7.tar.gz
rust-135ccbaca86ed4b9c0efaf0cd31442eae57ffad7.zip
Auto merge of #66908 - Centril:rollup-26givp6, r=Centril
Rollup of 9 pull requests

Successful merges:

 - #66612 (Initial implementation of or-pattern usefulness checking)
 - #66705 (Atomic as_mut_ptr)
 - #66759 (impl TrustedLen for vec::Drain)
 - #66858 (Use LLVMAddAnalysisPasses instead of Rust's wrapper)
 - #66870 (SimplifyArmIdentity only for locals with the same type)
 - #66883 (rustc_typeck: gate AnonConst's generics on feature(const_generics).)
 - #66889 (Make python-generated source files compatible with rustfmt)
 - #66894 (Remove unneeded prelude imports in libcore tests)
 - #66895 (Feature gating *declarations* => new crate `rustc_feature`)

Failed merges:

 - #66905 (rustc_plugin: Remove some remaining plugin features)

r? @ghost
Diffstat (limited to 'src/libsyntax/attr')
-rw-r--r--src/libsyntax/attr/builtin.rs57
1 files changed, 23 insertions, 34 deletions
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index c10541c8c7e..3c10f27b60a 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -1,7 +1,8 @@
 //! Parsing and validation of builtin attributes
 
+use super::{mark_used, MetaItemKind};
 use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
-use crate::feature_gate::{Features, GatedCfg};
+use crate::feature_gate::feature_err;
 use crate::print::pprust;
 use crate::sess::ParseSess;
 
@@ -9,12 +10,15 @@ use errors::{Applicability, Handler};
 use std::num::NonZeroU32;
 use syntax_pos::hygiene::Transparency;
 use syntax_pos::{symbol::Symbol, symbol::sym, Span};
+use rustc_feature::{Features, find_gated_cfg, GatedCfg, is_builtin_attr_name};
 use rustc_macros::HashStable_Generic;
 
-use super::{mark_used, MetaItemKind};
-
 use rustc_error_codes::*;
 
+pub fn is_builtin_attr(attr: &Attribute) -> bool {
+    attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
+}
+
 enum AttrError {
     MultipleItem(String),
     UnknownMetaItem(String, &'static [&'static str]),
@@ -24,31 +28,6 @@ enum AttrError {
     UnsupportedLiteral(&'static str, /* is_bytestr */ bool),
 }
 
-/// A template that the attribute input must match.
-/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
-#[derive(Clone, Copy)]
-pub struct AttributeTemplate {
-    pub word: bool,
-    pub list: Option<&'static str>,
-    pub name_value_str: Option<&'static str>,
-}
-
-impl AttributeTemplate {
-    pub fn only_word() -> Self {
-        Self { word: true, list: None, name_value_str: None }
-    }
-
-    /// Checks that the given meta-item is compatible with this template.
-    pub fn compatible(&self, meta_item_kind: &ast::MetaItemKind) -> bool {
-        match meta_item_kind {
-            ast::MetaItemKind::Word => self.word,
-            ast::MetaItemKind::List(..) => self.list.is_some(),
-            ast::MetaItemKind::NameValue(lit) if lit.kind.is_str() => self.name_value_str.is_some(),
-            ast::MetaItemKind::NameValue(..) => false,
-        }
-    }
-}
-
 fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
     let diag = &sess.span_diagnostic;
     match error {
@@ -555,8 +534,9 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
 /// Tests if a cfg-pattern matches the cfg set
 pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
     eval_condition(cfg, sess, &mut |cfg| {
-        if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
-            gated_cfg.check_and_emit(sess, feats);
+        let gate = find_gated_cfg(|sym| cfg.check_name(sym));
+        if let (Some(feats), Some(gated_cfg)) = (features, gate) {
+            gate_cfg(&gated_cfg, cfg.span, sess, feats);
         }
         let error = |span, msg| { sess.span_diagnostic.span_err(span, msg); true };
         if cfg.path.segments.len() != 1 {
@@ -585,12 +565,21 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
     })
 }
 
+fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) {
+    let (cfg, feature, has_feature) = gated_cfg;
+    if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
+        let explain = format!("`cfg({})` is experimental and subject to change", cfg);
+        feature_err(sess, *feature, cfg_span, &explain).emit()
+    }
+}
+
 /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
 /// evaluate individual items.
-pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
-                         -> bool
-    where F: FnMut(&ast::MetaItem) -> bool
-{
+pub fn eval_condition(
+    cfg: &ast::MetaItem,
+    sess: &ParseSess,
+    eval: &mut impl FnMut(&ast::MetaItem) -> bool,
+) -> bool {
     match cfg.kind {
         ast::MetaItemKind::List(ref mis) => {
             for mi in mis.iter() {