diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 934dfb54f6deb..6d2ee2426dd4a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -228,7 +228,9 @@ fn lint_unreachable( } } } - Some(_) => { /* for now we don't bother solving these */ } + Some(_) => { + // FIXME(https://github.com/rust-lang/rust/pull/149960#issuecomment-3780301699): expand capabilities. + } }, CfgEntry::Not(inner, _) => match &**inner { CfgEntry::NameValue { name, value: None, .. } => { @@ -247,7 +249,9 @@ fn lint_unreachable( } } } - _ => { /* for now we don't bother solving these */ } + _ => { + // FIXME(https://github.com/rust-lang/rust/pull/149960#issuecomment-3780301699): expand capabilities. + } }, CfgEntry::All(_, _) | CfgEntry::Any(_, _) => { /* for now we don't bother solving these */ diff --git a/compiler/rustc_attr_parsing/src/check_cfg.rs b/compiler/rustc_attr_parsing/src/check_cfg.rs index 44c44c6424b35..fe8a6b91c271a 100644 --- a/compiler/rustc_attr_parsing/src/check_cfg.rs +++ b/compiler/rustc_attr_parsing/src/check_cfg.rs @@ -49,7 +49,7 @@ fn to_check_cfg_arg(name: Ident, value: Option, quotes: EscapeQuotes) -> if let Some(value) = value { let value = str::escape_debug(value.as_str()).to_string(); let values = match quotes { - EscapeQuotes::Yes => format!("\\\"{}\\\"", value.replace("\"", "\\\\\\\\\"")), + EscapeQuotes::Yes => format!("\\\"{}\\\"", value.replace('"', "\\\\\\\\\"")), EscapeQuotes::No => format!("\"{value}\""), }; format!("cfg({name}, values({values}))") @@ -182,15 +182,15 @@ pub(crate) fn unexpected_cfg_name( possibilities.sort_by_key(|s| s.as_str()); let get_possibilities_sub = || { - if !possibilities.is_empty() { + if possibilities.is_empty() { + None + } else { let possibilities = - possibilities.iter().copied().cloned().collect::>().into(); + possibilities.iter().copied().copied().collect::>().into(); Some(diagnostics::unexpected_cfg_name::ExpectedValues { best_match, possibilities, }) - } else { - None } }; @@ -249,15 +249,15 @@ pub(crate) fn unexpected_cfg_name( let (possibilities, and_more) = sort_and_truncate_possibilities(sess, possibilities, FilterWellKnownNames::Yes); - let expected_names = if !possibilities.is_empty() { + let expected_names = if possibilities.is_empty() { + None + } else { let possibilities: Vec<_> = possibilities.into_iter().map(|s| Ident::new(s, name_span)).collect(); Some(diagnostics::unexpected_cfg_name::ExpectedNames { possibilities: possibilities.into(), and_more, }) - } else { - None }; diagnostics::unexpected_cfg_name::CodeSuggestion::SimilarValues { with_similar_values: similar_values, @@ -351,14 +351,12 @@ pub(crate) fn unexpected_cfg_value( let suggestion = if let Some((value, value_span)) = value { // Suggest the most probable if we found one - if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) { - Some(diagnostics::unexpected_cfg_value::ChangeValueSuggestion::SimilarName { + find_best_match_for_name(&possibilities, value, None).map(|best_match| { + diagnostics::unexpected_cfg_value::ChangeValueSuggestion::SimilarName { span: value_span, best_match, - }) - } else { - None - } + } + }) } else if let &[first_possibility] = &possibilities[..] { Some(diagnostics::unexpected_cfg_value::ChangeValueSuggestion::SpecifyValue { span: name_span.shrink_to_hi(), @@ -450,8 +448,7 @@ fn possible_well_known_names_for_cfg_value(sess: &Session, value: Symbol) -> Vec sess.check_config .expecteds .get(*name) - .map(|expected_values| expected_values.contains(&Some(value))) - .unwrap_or_default() + .is_some_and(|expected_values| expected_values.contains(&Some(value))) }) .copied() .collect::>(); diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 7ae275b940bd0..efa43562aeeca 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -93,7 +93,7 @@ pub(super) struct GroupTypeInnerAccept { } pub(crate) type AcceptFn = - Box Fn(&mut AcceptContext<'_, 'sess>, &ArgParser) + Send + Sync>; + Box Fn(&mut AcceptContext<'_, 'sess>, &ArgParser) + Send + Sync>; pub(crate) type FinalizeFn = fn(&mut FinalizeContext<'_, '_>) -> Option; macro_rules! attribute_parsers { @@ -463,7 +463,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { AttributeDiagnosticContext { ctx: self, custom_suggestions: Vec::new() } } - /// Asserts that this MetaItem is a list that contains a single element. Emits an error and + /// Asserts that this `MetaItem` is a list that contains a single element. Emits an error and /// returns `None` if it is not the case. /// /// Some examples: @@ -668,11 +668,7 @@ impl ExpectNameValue for MetaItemParser { cx.adcx().expected_name_value(self.span(), name); } - let Some((word, arg)) = word.zip(arg) else { - return None; - }; - - Some((word, arg)) + word.zip(arg) } } @@ -740,7 +736,7 @@ impl<'f, 'sess> Deref for AcceptContext<'f, 'sess> { } } -impl<'f, 'sess> DerefMut for AcceptContext<'f, 'sess> { +impl DerefMut for AcceptContext<'_, '_> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.shared } @@ -841,7 +837,7 @@ pub enum ShouldEmit { } impl ShouldEmit { - pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed { + pub(crate) fn emit_err(self, diag: Diag<'_>) -> ErrorGuaranteed { match self { ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(), ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(), @@ -865,16 +861,16 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { span: Span, reason: AttributeParseErrorReason<'_>, ) -> ErrorGuaranteed { - let suggestions = if !self.custom_suggestions.is_empty() { - AttributeParseErrorSuggestions::CreatedByParser(mem::take(&mut self.custom_suggestions)) - } else { + let suggestions = if self.custom_suggestions.is_empty() { AttributeParseErrorSuggestions::CreatedByTemplate(self.template_suggestions()) + } else { + AttributeParseErrorSuggestions::CreatedByParser(mem::take(&mut self.custom_suggestions)) }; self.emit_err(AttributeParseError { span, attr_span: self.attr_span, - template: self.template.clone(), + template: *self.template, path: self.attr_path.clone(), description: self.parsed_description, reason, @@ -1125,7 +1121,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { } } -impl<'a, 'f, 'sess: 'f> Deref for AttributeDiagnosticContext<'a, 'f, 'sess> { +impl<'f, 'sess: 'f> Deref for AttributeDiagnosticContext<'_, 'f, 'sess> { type Target = AcceptContext<'f, 'sess>; fn deref(&self) -> &Self::Target { @@ -1133,7 +1129,7 @@ impl<'a, 'f, 'sess: 'f> Deref for AttributeDiagnosticContext<'a, 'f, 'sess> { } } -impl<'a, 'f, 'sess: 'f> DerefMut for AttributeDiagnosticContext<'a, 'f, 'sess> { +impl<'f, 'sess: 'f> DerefMut for AttributeDiagnosticContext<'_, 'f, 'sess> { fn deref_mut(&mut self) -> &mut Self::Target { self.ctx } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index e360f5221c138..fa7a5bc4e5078 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -94,7 +94,7 @@ impl IllFormedAttributeInput { Self { num_suggestions: suggestions.len(), suggestions: DiagArgValue::StrListSepByAnd( - suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), + suggestions.iter().map(|s| format!("`{s}`").into()).collect(), ), has_docs: docs.is_some(), docs: docs.unwrap_or(""), diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 76efec612a7e2..54ba6c189b544 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -64,7 +64,7 @@ impl<'sess> AttributeParser<'sess> { /// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed /// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors /// - /// Due to this function not taking in RegisteredTools, *do not* use this for parsing any lint attributes + /// Due to this function not taking in `RegisteredTools`, *do not* use this for parsing any lint attributes pub fn parse_limited( sess: &'sess Session, attrs: &[ast::Attribute], @@ -86,7 +86,7 @@ impl<'sess> AttributeParser<'sess> { /// This does the same as `parse_limited`, except it has a `should_emit` parameter which allows it to emit errors. /// Usually you want `parse_limited`, which emits no errors. /// - /// Due to this function not taking in RegisteredTools, *do not* use this for parsing any lint attributes + /// Due to this function not taking in `RegisteredTools`, *do not* use this for parsing any lint attributes pub fn parse_limited_should_emit( sess: &'sess Session, attrs: &[ast::Attribute], @@ -256,7 +256,7 @@ impl<'sess> AttributeParser<'sess> { } pub(crate) fn sess(&self) -> &'sess Session { - &self.sess + self.sess } pub(crate) fn features(&self) -> &'sess Features { @@ -328,7 +328,6 @@ impl<'sess> AttributeParser<'sess> { } ast::AttrKind::Synthetic(synthetic) => { synthetic_attr_state.accept_synthetic_attr(attr_span, lower_span, synthetic); - continue; } ast::AttrKind::Normal(n) => { attr_paths.push(PathParser(&n.item.path)); @@ -347,7 +346,7 @@ impl<'sess> AttributeParser<'sess> { ); self.check_attribute_stability(&attr_path, attr_span, accept.stability); if let [part] = parts.as_slice() { - debug_assert!(BUILTIN_ATTRIBUTE_MAP.contains(&part)); + debug_assert!(BUILTIN_ATTRIBUTE_MAP.contains(part)); } let Some(args) = ArgParser::from_attr_args( @@ -417,7 +416,7 @@ impl<'sess> AttributeParser<'sess> { Self::check_target(&accept.allowed_targets, "", &mut cx); #[cfg(debug_assertions)] if !cx.shared.has_lint_been_emitted.load(Ordering::Relaxed) { - cx.shared.cx.check_args_used(&attr, &args) + cx.shared.cx.check_args_used(attr, &args) } } else { let attr = AttrItem { diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index c388b69af6484..ed926330ed289 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -72,11 +72,11 @@ impl> PathParser

{ self.word().map(|ident| ident.name) } - /// Asserts that this MetaItem is some specific word. + /// Asserts that this `MetaItem` is some specific word. /// /// See [`word`](Self::word) for examples of what a word is. pub fn word_is(&self, sym: Symbol) -> bool { - self.word().map(|i| i.name == sym).unwrap_or(false) + self.word().is_some_and(|i| i.name == sym) } /// Checks whether the first segments match the givens. @@ -175,7 +175,7 @@ impl ArgParser { } AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser { eq_span: *eq_span, - value: expr_to_lit(psess, &expr, expr.span, should_emit) + value: expr_to_lit(psess, expr, expr.span, should_emit) .map_err(|e| should_emit.emit_err(e)) .ok()??, value_span: expr.span, @@ -183,7 +183,7 @@ impl ArgParser { }) } - /// Asserts that this MetaItem is a list + /// Asserts that this `MetaItem` is a list /// /// Some examples: /// @@ -196,7 +196,7 @@ impl ArgParser { } } - /// Asserts that this MetaItem is a name-value pair. + /// Asserts that this `MetaItem` is a name-value pair. /// /// Some examples: /// @@ -226,13 +226,10 @@ impl ArgParser { /// Explicitly ignore the arguments, disarming the arguments-used check pub fn ignore_args(&self) { #[cfg(debug_assertions)] - match self { - ArgParser::List(list) => { - for item in list.mixed() { - item.ignore_args(); - } + if let ArgParser::List(list) = self { + for item in list.mixed() { + item.ignore_args(); } - _ => {} } } } @@ -284,7 +281,7 @@ impl MetaItemOrLitParser { pub fn meta_item_no_args(&self) -> Option<&MetaItemParser> { let meta_item = self.meta_item()?; match meta_item.args().as_no_args() { - Ok(_) => Some(meta_item), + Ok(()) => Some(meta_item), Err(_) => None, } } @@ -301,15 +298,15 @@ impl MetaItemOrLitParser { } } -/// Utility that deconstructs a MetaItem into usable parts. +/// Utility that deconstructs a `MetaItem` into usable parts. /// -/// MetaItems are syntactically extremely flexible, but specific attributes want to parse +/// `MetaItems` are syntactically extremely flexible, but specific attributes want to parse /// them in custom, more restricted ways. For common argument shapes, prefer the higher-level /// [`AcceptContext::expect_list`](crate::context::AcceptContext::expect_list) and /// [`AcceptContext::expect_single`](crate::context::AcceptContext::expect_single) helpers. /// Use this struct when parsing a custom restricted syntax. /// -/// MetaItems consist of some path, and some args. The args could be empty. In other words: +/// `MetaItems` consist of some path, and some args. The args could be empty. In other words: /// /// - `name` -> args are empty /// - `name(...)` -> args are a [`list`](ArgParser::as_list), which is the bit between the @@ -317,7 +314,7 @@ impl MetaItemOrLitParser { /// - `name = value`-> arg is [`name_value`](ArgParser::as_name_value), where the argument is the /// `= value` part /// -/// The syntax of MetaItems can be found at +/// The syntax of `MetaItems` can be found at pub struct MetaItemParser { path: OwnedPathParser, args: ArgParser, @@ -367,7 +364,7 @@ impl MetaItemParser { &self.args } - /// Asserts that this MetaItem starts with a word, or single segment path. + /// Asserts that this `MetaItem` starts with a word, or single segment path. /// /// Some examples: /// - `#[inline]`: `inline` is a word @@ -438,12 +435,10 @@ fn expr_to_lit<'sess>( Ok(lit) => { if token_lit.suffix.is_some() { Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span })) + } else if lit.kind.is_unsuffixed() { + Ok(Some(lit)) } else { - if lit.kind.is_unsuffixed() { - Ok(Some(lit)) - } else { - Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span })) - } + Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span })) } } Err(err) => { @@ -523,7 +518,7 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { Ok(lit) => lit, Err(err) => { return Err(create_lit_error( - &self.parser.psess, + self.parser.psess, err, token_lit, self.parser.prev_token_uninterpolated_span(), @@ -539,9 +534,8 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } ) { return Err(err); - } else { - self.should_emit.emit_err(err) - }; + } + self.should_emit.emit_err(err); } Ok(lit) @@ -630,11 +624,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { Err(err) => { // If `parse_attr_item` made any progress, it likely has a more precise error we should prefer // If it didn't make progress we use the `expected_lit` from below - if self.parser.approx_token_stream_pos() != prev_pros { - Err(err) - } else { + if self.parser.approx_token_stream_pos() == prev_pros { err.cancel(); Err(self.expected_lit()) + } else { + Err(err) } } } diff --git a/compiler/rustc_attr_parsing/src/safety.rs b/compiler/rustc_attr_parsing/src/safety.rs index 5b1e50ffa5603..5b3d52c18aae1 100644 --- a/compiler/rustc_attr_parsing/src/safety.rs +++ b/compiler/rustc_attr_parsing/src/safety.rs @@ -24,9 +24,11 @@ impl<'sess> AttributeParser<'sess> { // Check if expected & actual safety match match (expected_safety, attr_safety) { - // - Unsafe builtin attribute - // - User wrote `#[unsafe(..)]`, which is permitted on any edition - (AttributeSafety::Unsafe { .. }, Safety::Unsafe(..)) => { + // - An unsafe builtin attribute, where the user wrote `#[unsafe(..)]`, + // which is permitted on any edition + // - A normal builtin attribute, where no explicit `#[unsafe(..)]` was written. + (AttributeSafety::Unsafe { .. }, Safety::Unsafe(..)) + | (AttributeSafety::Normal, Safety::Default) => { // OK } @@ -57,7 +59,7 @@ impl<'sess> AttributeParser<'sess> { && let Ok(mut snippet) = self.sess.source_map().span_to_snippet(diag_span) { snippet.retain(|c| !c.is_whitespace()); - if snippet.contains("!(") || snippet.starts_with("#[") && snippet.ends_with("]") + if snippet.contains("!(") || snippet.starts_with("#[") && snippet.ends_with(']') { not_from_proc_macro = false; } @@ -101,12 +103,6 @@ impl<'sess> AttributeParser<'sess> { }); } - // - Normal builtin attribute - // - No explicit `#[unsafe(..)]` written. - (AttributeSafety::Normal, Safety::Default) => { - // OK - } - (_, Safety::Safe(..)) => { self.sess.dcx().span_delayed_bug( attr_span, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 9e5d7bb2cf375..cbcec3ac22231 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -610,8 +610,8 @@ impl<'a> AttributeParseError<'a> { for Suggestion { msg, sp, code } in suggestions { diag.span_suggestion_verbose( *sp, - msg.to_string(), - code.to_string(), + msg.clone(), + code.clone(), Applicability::MaybeIncorrect, ); } @@ -659,9 +659,8 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { // Avoid emitting an "attribute must be of the form" suggestion, as the // attribute is likely to be well-formed already. return diag; - } else { - diag.span_label(self.span, "expected a string literal here"); } + diag.span_label(self.span, "expected a string literal here"); } AttributeParseErrorReason::ExpectedFilenameLiteral => { diag.span_label(self.span, "expected a filename string literal here"); @@ -721,10 +720,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { AttributeParseErrorReason::ExpectedNameValue(None) => { // If the span is the entire attribute, the suggestion we add below this match already contains enough information if self.span != self.attr_span { - diag.span_label( - self.span, - format!("expected this to be of the form `... = \"...\"`"), - ); + diag.span_label(self.span, "expected this to be of the form `... = \"...\"`"); } } AttributeParseErrorReason::ExpectedNameValue(Some(name)) => { @@ -741,14 +737,14 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { strings, list: false, } => { - self.render_expected_specific_argument(&mut diag, *possibilities, *strings); + self.render_expected_specific_argument(&mut diag, possibilities, *strings); } AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings, list: true, } => { - self.render_expected_specific_argument_list(&mut diag, *possibilities, *strings); + self.render_expected_specific_argument_list(&mut diag, possibilities, *strings); } AttributeParseErrorReason::ExpectedIdentifier => { diag.span_label(self.span, "expected a valid identifier here"); diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 03100381d23f3..636df0849290c 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -62,16 +62,13 @@ impl AllowedTargets<'_> { pub(crate) fn allowed_targets(&self) -> Vec { match self { - AllowedTargets::AllowList(list) => list, - AllowedTargets::AllowListWarnRest(list) => list, + AllowedTargets::AllowList(list) | AllowedTargets::AllowListWarnRest(list) => list, AllowedTargets::ManuallyChecked => unreachable!(), } .iter() .filter_map(|target| match target { Policy::Allow(target) => Some(*target), - Policy::AllowSilent(_) => None, // Not listed in possible targets - Policy::Warn(_) => None, - Policy::Error(_) => None, + Policy::AllowSilent(_) | Policy::Warn(_) | Policy::Error(_) => None, }) .collect() } @@ -132,7 +129,7 @@ impl<'sess> AttributeParser<'sess> { let is_diagnostic_attr = cx.attr_path.segments[0] == sym::diagnostic; let diag = InvalidTarget { - span: cx.attr_span.clone(), + span: cx.attr_span, name: cx.attr_path.clone(), target: cx.target.plural_name(), only: if only { "only " } else { "" }, @@ -163,7 +160,7 @@ impl<'sess> AttributeParser<'sess> { rustc_session::lint::builtin::UNUSED_ATTRIBUTES }; - let attr_span = cx.attr_span.clone(); + let attr_span = cx.attr_span; cx.emit_lint(lint, diag, attr_span); } AllowedResult::Error => { @@ -463,7 +460,7 @@ impl<'f, 'sess> AcceptContext<'f, 'sess> { /// This is used for: /// - `rustc_dummy`, which can be applied to all targets /// - Attributes that are not parted to the new target system yet can use this list as a placeholder -pub(crate) const ALL_TARGETS: &'static [Policy] = { +pub(crate) const ALL_TARGETS: &[Policy] = { use Policy::Allow; &[ Allow(Target::ExternCrate), diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs index daec803a27a24..90380c08fdba1 100644 --- a/compiler/rustc_attr_parsing/src/validate_attr.rs +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -24,48 +24,44 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { use ast::SyntheticAttr::*; match &attr.kind { AttrKind::Normal(_) => {} - AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) => return, - AttrKind::DocComment(..) => return, + AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) | AttrKind::DocComment(..) => return, } let builtin_attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)); // Check input tokens for built-in and key-value attributes. - match builtin_attr_info { - Some(name) => { - if AttributeParser::is_parsed_attribute(slice::from_ref(&name)) { - return; + if let Some(name) = builtin_attr_info { + if AttributeParser::is_parsed_attribute(slice::from_ref(name)) { + return; + } + match parse_meta(psess, attr) { + // Don't check safety again, we just did that + Ok(meta) => { + // FIXME The only unparsed builtin attributes that are left are the lint attributes, so we can hardcode the template here + let lint_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect]; + assert!(lint_attrs.contains(name)); + + let template = template!( + List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" + ); + check_builtin_meta_item(psess, &meta, attr.style, *name, template, false) } + Err(err) => { + err.emit(); + } + } + } else { + let attr_item = attr.get_normal_item(); + if let AttrArgs::Eq { .. } = attr_item.args { + // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { - // Don't check safety again, we just did that - Ok(meta) => { - // FIXME The only unparsed builtin attributes that are left are the lint attributes, so we can hardcode the template here - let lint_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect]; - assert!(lint_attrs.contains(name)); - - let template = template!( - List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" - ); - check_builtin_meta_item(psess, &meta, attr.style, *name, template, false) - } + Ok(_) => {} Err(err) => { err.emit(); } } } - _ => { - let attr_item = attr.get_normal_item(); - if let AttrArgs::Eq { .. } = attr_item.args { - // All key-value attributes are restricted to meta-item syntax. - match parse_meta(psess, attr) { - Ok(_) => {} - Err(err) => { - err.emit(); - } - } - } - } } } @@ -86,7 +82,8 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met AttrArgs::Eq { expr, .. } => { if let ast::ExprKind::Lit(token_lit) = expr.kind { let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span); - let res = match res { + + match res { Ok(lit) => { if token_lit.suffix.is_some() { let mut err = psess.dcx().struct_span_err( @@ -98,9 +95,8 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met use an unsuffixed version (`1`, `1.0`, etc.)", ); return Err(err); - } else { - MetaItemKind::NameValue(lit) } + MetaItemKind::NameValue(lit) } Err(err) => { let guar = report_lit_error(psess, err, token_lit, expr.span); @@ -112,8 +108,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met }; MetaItemKind::NameValue(lit) } - }; - res + } } else { // Example cases: // - `#[foo = 1+1]`: results in `ast::ExprKind::Binary`.