about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast.rs7
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs66
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs88
-rw-r--r--compiler/rustc_passes/src/lib_features.rs5
4 files changed, 90 insertions, 76 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 8ad3270c510..f2258fecfea 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1826,6 +1826,13 @@ pub enum LitKind {
 }
 
 impl LitKind {
+    pub fn str(&self) -> Option<Symbol> {
+        match *self {
+            LitKind::Str(s, _) => Some(s),
+            _ => None,
+        }
+    }
+
     /// Returns `true` if this literal is a string.
     pub fn is_str(&self) -> bool {
         matches!(self, LitKind::Str(..))
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index c6b6207b318..cd60506dd80 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -140,17 +140,14 @@ impl Attribute {
 
     pub fn value_str(&self) -> Option<Symbol> {
         match &self.kind {
-            AttrKind::Normal(normal) => normal.item.meta_kind().and_then(|kind| kind.value_str()),
+            AttrKind::Normal(normal) => normal.item.value_str(),
             AttrKind::DocComment(..) => None,
         }
     }
 
     pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
         match &self.kind {
-            AttrKind::Normal(normal) => match normal.item.meta_kind() {
-                Some(MetaItemKind::List(list)) => Some(list),
-                _ => None,
-            },
+            AttrKind::Normal(normal) => normal.item.meta_item_list(),
             AttrKind::DocComment(..) => None,
         }
     }
@@ -216,6 +213,20 @@ impl MetaItem {
     }
 }
 
+impl AttrArgsEq {
+    fn value_str(&self) -> Option<Symbol> {
+        match self {
+            AttrArgsEq::Ast(expr) => match expr.kind {
+                ExprKind::Lit(token_lit) => {
+                    LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
+                }
+                _ => None,
+            },
+            AttrArgsEq::Hir(lit) => lit.kind.str(),
+        }
+    }
+}
+
 impl AttrItem {
     pub fn span(&self) -> Span {
         self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
@@ -228,6 +239,22 @@ impl AttrItem {
     pub fn meta_kind(&self) -> Option<MetaItemKind> {
         MetaItemKind::from_attr_args(&self.args)
     }
+
+    fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
+        match &self.args {
+            AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => {
+                MetaItemKind::list_from_tokens(args.tokens.clone())
+            }
+            AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
+        }
+    }
+
+    fn value_str(&self) -> Option<Symbol> {
+        match &self.args {
+            AttrArgs::Eq(_, args) => args.value_str(),
+            AttrArgs::Delimited(_) | AttrArgs::Empty => None,
+        }
+    }
 }
 
 impl Attribute {
@@ -247,13 +274,11 @@ impl Attribute {
     /// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
     /// * `#[doc(...)]` returns `None`.
     pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
-        match self.kind {
-            AttrKind::DocComment(kind, data) => Some((data, kind)),
-            AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal
-                .item
-                .meta_kind()
-                .and_then(|kind| kind.value_str())
-                .map(|data| (data, CommentKind::Line)),
+        match &self.kind {
+            AttrKind::DocComment(kind, data) => Some((*data, *kind)),
+            AttrKind::Normal(normal) if normal.item.path == sym::doc => {
+                normal.item.value_str().map(|s| (s, CommentKind::Line))
+            }
             _ => None,
         }
     }
@@ -265,9 +290,7 @@ impl Attribute {
     pub fn doc_str(&self) -> Option<Symbol> {
         match &self.kind {
             AttrKind::DocComment(.., data) => Some(*data),
-            AttrKind::Normal(normal) if normal.item.path == sym::doc => {
-                normal.item.meta_kind().and_then(|kind| kind.value_str())
-            }
+            AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
             _ => None,
         }
     }
@@ -508,15 +531,12 @@ impl MetaItem {
 impl MetaItemKind {
     pub fn value_str(&self) -> Option<Symbol> {
         match self {
-            MetaItemKind::NameValue(v) => match v.kind {
-                LitKind::Str(s, _) => Some(s),
-                _ => None,
-            },
+            MetaItemKind::NameValue(v) => v.kind.str(),
             _ => None,
         }
     }
 
-    fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
+    fn list_from_tokens(tokens: TokenStream) -> Option<Vec<NestedMetaItem>> {
         let mut tokens = tokens.into_trees().peekable();
         let mut result = Vec::new();
         while tokens.peek().is_some() {
@@ -527,7 +547,7 @@ impl MetaItemKind {
                 _ => return None,
             }
         }
-        Some(MetaItemKind::List(result))
+        Some(result)
     }
 
     fn name_value_from_tokens(
@@ -551,7 +571,7 @@ impl MetaItemKind {
                 dspan: _,
                 delim: MacDelimiter::Parenthesis,
                 tokens,
-            }) => MetaItemKind::list_from_tokens(tokens.clone()),
+            }) => MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List),
             AttrArgs::Delimited(..) => None,
             AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
                 ExprKind::Lit(token_lit) => {
@@ -573,7 +593,7 @@ impl MetaItemKind {
             Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
                 let inner_tokens = inner_tokens.clone();
                 tokens.next();
-                MetaItemKind::list_from_tokens(inner_tokens)
+                MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
             }
             Some(TokenTree::Delimited(..)) => None,
             Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 9831e98fe37..3ebbb2cbdfb 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -319,74 +319,62 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
                 }
             }
         } else if attr.has_name(sym::instruction_set) {
-            codegen_fn_attrs.instruction_set = match attr.meta_kind() {
-                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
-                    [NestedMetaItem::MetaItem(set)] => {
-                        let segments =
-                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
-                        match segments.as_slice() {
-                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
-                                if !tcx.sess.target.has_thumb_interworking {
-                                    struct_span_err!(
-                                        tcx.sess.diagnostic(),
-                                        attr.span,
-                                        E0779,
-                                        "target does not support `#[instruction_set]`"
-                                    )
-                                    .emit();
-                                    None
-                                } else if segments[1] == sym::a32 {
-                                    Some(InstructionSetAttr::ArmA32)
-                                } else if segments[1] == sym::t32 {
-                                    Some(InstructionSetAttr::ArmT32)
-                                } else {
-                                    unreachable!()
-                                }
-                            }
-                            _ => {
+            codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] {
+                [NestedMetaItem::MetaItem(set)] => {
+                    let segments =
+                        set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+                    match segments.as_slice() {
+                        [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+                            if !tcx.sess.target.has_thumb_interworking {
                                 struct_span_err!(
                                     tcx.sess.diagnostic(),
                                     attr.span,
                                     E0779,
-                                    "invalid instruction set specified",
+                                    "target does not support `#[instruction_set]`"
                                 )
                                 .emit();
                                 None
+                            } else if segments[1] == sym::a32 {
+                                Some(InstructionSetAttr::ArmA32)
+                            } else if segments[1] == sym::t32 {
+                                Some(InstructionSetAttr::ArmT32)
+                            } else {
+                                unreachable!()
                             }
                         }
+                        _ => {
+                            struct_span_err!(
+                                tcx.sess.diagnostic(),
+                                attr.span,
+                                E0779,
+                                "invalid instruction set specified",
+                            )
+                            .emit();
+                            None
+                        }
                     }
-                    [] => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0778,
-                            "`#[instruction_set]` requires an argument"
-                        )
-                        .emit();
-                        None
-                    }
-                    _ => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0779,
-                            "cannot specify more than one instruction set"
-                        )
-                        .emit();
-                        None
-                    }
-                },
-                _ => {
+                }
+                [] => {
                     struct_span_err!(
                         tcx.sess.diagnostic(),
                         attr.span,
                         E0778,
-                        "must specify an instruction set"
+                        "`#[instruction_set]` requires an argument"
                     )
                     .emit();
                     None
                 }
-            };
+                _ => {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0779,
+                        "cannot specify more than one instruction set"
+                    )
+                    .emit();
+                    None
+                }
+            })
         } else if attr.has_name(sym::repr) {
             codegen_fn_attrs.alignment = match attr.meta_item_list() {
                 Some(items) => match items.as_slice() {
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 4c6a9b23fdf..f4da1aaec11 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -4,7 +4,7 @@
 //! but are not declared in one single location (unlike lang features), which means we need to
 //! collect them instead.
 
-use rustc_ast::{Attribute, MetaItemKind};
+use rustc_ast::Attribute;
 use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
@@ -42,8 +42,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
         // Find a stability attribute: one of #[stable(…)], #[unstable(…)],
         // #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
         if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
-            let meta_kind = attr.meta_kind();
-            if let Some(MetaItemKind::List(ref metas)) = meta_kind {
+            if let Some(metas) = attr.meta_item_list() {
                 let mut feature = None;
                 let mut since = None;
                 for meta in metas {