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 { + 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 @@ pub fn name_or_empty(&self) -> Symbol { pub fn value_str(&self) -> Option { 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> { 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 @@ pub fn name_value_literal_span(&self) -> Option { } } +impl AttrArgsEq { + fn value_str(&self) -> Option { + 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 @@ pub fn meta(&self, span: Span) -> Option { pub fn meta_kind(&self) -> Option { MetaItemKind::from_attr_args(&self.args) } + + fn meta_item_list(&self) -> Option> { + 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 { + match &self.args { + AttrArgs::Eq(_, args) => args.value_str(), + AttrArgs::Delimited(_) | AttrArgs::Empty => None, + } + } } impl Attribute { @@ -247,13 +274,11 @@ pub fn is_doc_comment(&self) -> bool { /// * `#[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 @@ pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> { pub fn doc_str(&self) -> Option { 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 @@ fn from_tokens(tokens: &mut iter::Peekable) -> Option impl MetaItemKind { pub fn value_str(&self) -> Option { 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 { + fn list_from_tokens(tokens: TokenStream) -> Option> { let mut tokens = tokens.into_trees().peekable(); let mut result = Vec::new(); while tokens.peek().is_some() { @@ -527,7 +547,7 @@ fn list_from_tokens(tokens: TokenStream) -> Option { _ => return None, } } - Some(MetaItemKind::List(result)) + Some(result) } fn name_value_from_tokens( @@ -551,7 +571,7 @@ fn from_attr_args(args: &AttrArgs) -> Option { 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 @@ fn from_tokens( 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::>(); - 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::>(); + 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 @@ fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { // 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 {