diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index d37ede86cfd2a..8460a4a412279 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -53,7 +53,7 @@ fn parse_unstable<'a>( for param in list.mixed() { let param_span = param.span(); - if let Some(ident) = param.meta_item().and_then(|i| i.word_without_args()) { + if let Some(ident) = param.meta_item().and_then(|i| i.path().word()) { res.push(ident.name); } else { cx.emit_err(session_diagnostics::ExpectsFeatures { diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 7d1417446b21d..5e94261f1c49a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -1,5 +1,4 @@ use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation}; -use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol, sym}; use super::SingleAttributeParser; @@ -13,16 +12,13 @@ pub(crate) struct DeprecationParser; fn get( cx: &AcceptContext<'_>, - ident: Ident, + name: Symbol, param_span: Span, arg: &ArgParser<'_>, item: &Option, ) -> Option { if item.is_some() { - cx.emit_err(session_diagnostics::MultipleItem { - span: param_span, - item: ident.to_string(), - }); + cx.emit_err(session_diagnostics::MultipleItem { span: param_span, item: name.to_string() }); return None; } if let Some(v) = arg.name_value() { @@ -83,16 +79,16 @@ impl SingleAttributeParser for DeprecationParser { return None; }; - let (ident, arg) = param.word_or_empty(); + let ident_name = param.path().word_sym(); - match ident.name { - sym::since => { - since = Some(get(cx, ident, param_span, arg, &since)?); + match ident_name { + Some(name @ sym::since) => { + since = Some(get(cx, name, param_span, param.args(), &since)?); } - sym::note => { - note = Some(get(cx, ident, param_span, arg, ¬e)?); + Some(name @ sym::note) => { + note = Some(get(cx, name, param_span, param.args(), ¬e)?); } - sym::suggestion => { + Some(name @ sym::suggestion) => { if !features.deprecated_suggestion() { cx.emit_err(session_diagnostics::DeprecatedItemSuggestion { span: param_span, @@ -101,12 +97,12 @@ impl SingleAttributeParser for DeprecationParser { }); } - suggestion = Some(get(cx, ident, param_span, arg, &suggestion)?); + suggestion = Some(get(cx, name, param_span, param.args(), &suggestion)?); } _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param_span, - item: ident.to_string(), + item: param.path().to_string(), expected: if features.deprecated_suggestion() { &["since", "note", "suggestion"] } else { diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 26ca637faec68..aac6897119e63 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -96,57 +96,65 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option { - cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident.span }); + let ident = param.path().word(); + let ident_span = ident.map_or(rustc_span::DUMMY_SP, |ident| ident.span); + let name = ident.map(|ident| ident.name); + let args = param.args(); + + match (name, args) { + (Some(sym::align), ArgParser::NoArgs) => { + cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident_span }); None } - (sym::align, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Align), + (Some(sym::align), ArgParser::List(l)) => { + parse_repr_align(cx, l, param.span(), AlignKind::Align) + } - (sym::packed, ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), - (sym::packed, ArgParser::List(l)) => { + (Some(sym::packed), ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), + (Some(sym::packed), ArgParser::List(l)) => { parse_repr_align(cx, l, param.span(), AlignKind::Packed) } - (sym::align | sym::packed, ArgParser::NameValue(l)) => { + (Some(sym::align | sym::packed), ArgParser::NameValue(l)) => { cx.emit_err(session_diagnostics::IncorrectReprFormatGeneric { span: param.span(), // FIXME(jdonszelmann) can just be a string in the diag type - repr_arg: &ident.to_string(), + repr_arg: &ident.unwrap().to_string(), cause: IncorrectReprFormatGenericCause::from_lit_kind( param.span(), &l.value_as_lit().kind, - ident.name.as_str(), + ident.unwrap().as_str(), ), }); None } - (sym::Rust, ArgParser::NoArgs) => Some(ReprRust), - (sym::C, ArgParser::NoArgs) => Some(ReprC), - (sym::simd, ArgParser::NoArgs) => Some(ReprSimd), - (sym::transparent, ArgParser::NoArgs) => Some(ReprTransparent), - (i @ int_pat!(), ArgParser::NoArgs) => { + (Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust), + (Some(sym::C), ArgParser::NoArgs) => Some(ReprC), + (Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd), + (Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent), + (Some(i @ int_pat!()), ArgParser::NoArgs) => { // int_pat!() should make sure it always parses Some(ReprInt(int_type_of_word(i).unwrap())) } ( - sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), + Some(sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!()), ArgParser::NameValue(_), ) => { cx.emit_err(session_diagnostics::InvalidReprHintNoValue { span: param.span(), - name: ident.to_string(), + name: ident.unwrap().to_string(), }); None } - (sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::List(_)) => { + ( + Some(sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!()), + ArgParser::List(_), + ) => { cx.emit_err(session_diagnostics::InvalidReprHintNoParen { span: param.span(), - name: ident.to_string(), + name: ident.unwrap().to_string(), }); None } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index bdad6b50186dd..cea16a9e45f6e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -204,7 +204,7 @@ fn insert_value_into_option_or_error( if item.is_some() { cx.emit_err(session_diagnostics::MultipleItem { span: param.span(), - item: param.path_without_args().to_string(), + item: param.path().to_string(), }); None } else if let Some(v) = param.args().name_value() @@ -242,13 +242,13 @@ pub(crate) fn parse_stability( return None; }; - match param.word_or_empty_without_args().name { - sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, - sym::since => insert_value_into_option_or_error(cx, ¶m, &mut since)?, + match param.path().word_sym() { + Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, + Some(sym::since) => insert_value_into_option_or_error(cx, ¶m, &mut since)?, _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param_span, - item: param.path_without_args().to_string(), + item: param.path().to_string(), expected: &["feature", "since"], }); return None; @@ -310,11 +310,10 @@ pub(crate) fn parse_unstability( return None; }; - let (word, args) = param.word_or_empty(); - match word.name { - sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, - sym::reason => insert_value_into_option_or_error(cx, ¶m, &mut reason)?, - sym::issue => { + match param.path().word_sym() { + Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?, + Some(sym::reason) => insert_value_into_option_or_error(cx, ¶m, &mut reason)?, + Some(sym::issue) => { insert_value_into_option_or_error(cx, ¶m, &mut issue)?; // These unwraps are safe because `insert_value_into_option_or_error` ensures the meta item @@ -328,7 +327,7 @@ pub(crate) fn parse_unstability( session_diagnostics::InvalidIssueString { span: param.span(), cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind( - args.name_value().unwrap().value_span, + param.args().name_value().unwrap().value_span, err.kind(), ), }, @@ -338,17 +337,19 @@ pub(crate) fn parse_unstability( }, }; } - sym::soft => { - if !args.no_args() { + Some(sym::soft) => { + if !param.args().no_args() { cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() }); } is_soft = true; } - sym::implied_by => insert_value_into_option_or_error(cx, ¶m, &mut implied_by)?, + Some(sym::implied_by) => { + insert_value_into_option_or_error(cx, ¶m, &mut implied_by)? + } _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param.span(), - item: param.path_without_args().to_string(), + item: param.path().to_string(), expected: &["feature", "reason", "issue", "soft", "implied_by"], }); return None; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 55c3df003fe16..c101785491665 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -260,7 +260,8 @@ impl<'sess> AttributeParser<'sess> { // } ast::AttrKind::Normal(n) => { let parser = MetaItemParser::from_attr(n, self.dcx()); - let (path, args) = parser.deconstruct(); + let path = parser.path(); + let args = parser.args(); let parts = path.segments().map(|i| i.name).collect::>(); if let Some(accepts) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) { diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 40aa39711d3e2..6b20108a6e470 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -78,8 +78,8 @@ impl<'a> PathParser<'a> { (self.len() == 1).then(|| **self.segments().next().as_ref().unwrap()) } - pub fn word_or_empty(&self) -> Ident { - self.word().unwrap_or_else(Ident::empty) + pub fn word_sym(&self) -> Option { + self.word().map(|ident| ident.name) } /// Asserts that this MetaItem is some specific word. @@ -253,71 +253,28 @@ impl<'a> MetaItemParser<'a> { } } - /// Gets just the path, without the args. - pub fn path_without_args(&self) -> PathParser<'a> { - self.path.clone() - } - - /// Gets just the args parser, without caring about the path. - pub fn args(&self) -> &ArgParser<'a> { - &self.args - } - - pub fn deconstruct(&self) -> (PathParser<'a>, &ArgParser<'a>) { - (self.path_without_args(), self.args()) - } - - /// Asserts that this MetaItem starts with a path. Some examples: + /// Gets a `PathParser` for a path. Some examples: /// /// - `#[rustfmt::skip]`: `rustfmt::skip` is a path /// - `#[allow(clippy::complexity)]`: `clippy::complexity` is a path /// - `#[inline]`: `inline` is a single segment path - pub fn path(&self) -> (PathParser<'a>, &ArgParser<'a>) { - self.deconstruct() - } - - /// Asserts that this MetaItem starts with a word, or single segment path. - /// Doesn't return the args parser. - /// - /// For examples. see [`Self::word`] - pub fn word_without_args(&self) -> Option { - Some(self.word()?.0) + pub fn path(&self) -> &PathParser<'a> { + &self.path } - /// Like [`word`](Self::word), but returns an empty symbol instead of None - pub fn word_or_empty_without_args(&self) -> Ident { - self.word_or_empty().0 + /// Gets just the args parser, without caring about the path. + pub fn args(&self) -> &ArgParser<'a> { + &self.args } - /// Asserts that this MetaItem starts with a word, or single segment path. + /// Asserts that this MetaItem starts with some specific word. /// /// Some examples: /// - `#[inline]`: `inline` is a word /// - `#[rustfmt::skip]`: `rustfmt::skip` is a path, /// and not a word and should instead be parsed using [`path`](Self::path) - pub fn word(&self) -> Option<(Ident, &ArgParser<'a>)> { - let (path, args) = self.deconstruct(); - Some((path.word()?, args)) - } - - /// Like [`word`](Self::word), but returns an empty symbol instead of None - pub fn word_or_empty(&self) -> (Ident, &ArgParser<'a>) { - let (path, args) = self.deconstruct(); - (path.word().unwrap_or(Ident::empty()), args) - } - - /// Asserts that this MetaItem starts with some specific word. - /// - /// See [`word`](Self::word) for examples of what a word is. pub fn word_is(&self, sym: Symbol) -> Option<&ArgParser<'a>> { - self.path_without_args().word_is(sym).then(|| self.args()) - } - - /// Asserts that this MetaItem starts with some specific path. - /// - /// See [`word`](Self::path) for examples of what a word is. - pub fn path_is(&self, segments: &[Symbol]) -> Option<&ArgParser<'a>> { - self.path_without_args().segments_is(segments).then(|| self.args()) + self.path().word_is(sym).then(|| self.args()) } } @@ -560,7 +517,7 @@ impl<'a> MetaItemListParser<'a> { } /// Lets you pick and choose as what you want to parse each element in the list - pub fn mixed<'s>(&'s self) -> impl Iterator> + 's { + pub fn mixed(&self) -> impl Iterator> + '_ { self.sub_parsers.iter() } @@ -572,20 +529,6 @@ impl<'a> MetaItemListParser<'a> { self.len() == 0 } - /// Asserts that every item in the list is another list starting with a word. - /// - /// See [`MetaItemParser::word`] for examples of words. - pub fn all_word_list<'s>(&'s self) -> Option)>> { - self.mixed().map(|i| i.meta_item()?.word()).collect() - } - - /// Asserts that every item in the list is another list starting with a full path. - /// - /// See [`MetaItemParser::path`] for examples of paths. - pub fn all_path_list<'s>(&'s self) -> Option, &'s ArgParser<'a>)>> { - self.mixed().map(|i| Some(i.meta_item()?.path())).collect() - } - /// Returns Some if the list contains only a single element. /// /// Inside the Some is the parser to parse this single element.